/* * OMAP3 image quality tuning * * Copyright (C) 2010-2012 Ideas on board SPRL * * Contact: Laurent Pinchart * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "isp/omap3isp.h" #include "isp/stats.h" #include "isp/tools.h" #include "iq.h" struct iq_tuning { struct omap3_isp_device *isp; unsigned int frame_count; unsigned int pix_max; float mean_level; unsigned int exposure; unsigned int exposure_min; unsigned int exposure_max; unsigned int gain; unsigned int gain_min; unsigned int gain_max; unsigned int black_level; }; void iq_aewb_process(struct iq_tuning *iq, const struct omap3_isp_aewb_stats *stats) { unsigned int i; float gains[4]; double factor; double gain; double mean; /* Automatic White Balance */ mean = stats->accum[0] + stats->accum[3] + (stats->accum[1] + stats->accum[2]) / 2; mean /= 3; for (i = 0; i < 4; ++i) gains[i] = mean / stats->accum[i]; omap3_isp_preview_set_white_balance(iq->isp, gains); /* Automatic Exposure */ if ((iq->frame_count++ % 2) == 0) return; mean = stats->accum[0] + stats->accum[1] + stats->accum[2] + stats->accum[3]; mean /= 4 * stats->npix; factor = (iq->pix_max * iq->mean_level) / mean; gain = factor * iq->exposure * iq->gain / iq->gain_min; iq->exposure = clamp((unsigned int)gain, iq->exposure_min, iq->exposure_max); gain = gain / iq->exposure * iq->gain_min; iq->gain = clamp((unsigned int)gain, iq->gain_min, iq->gain_max); printf("AE: factor %.4f exposure %u sensor gain %u\n", factor, iq->exposure, iq->gain); omap3_isp_sensor_set_exposure(iq->isp, iq->exposure); omap3_isp_sensor_set_gain(iq->isp, iq->gain); } struct iq_tuning *iq_init(struct omap3_isp_device *isp) { struct v4l2_mbus_framefmt format; struct v4l2_rect window; struct iq_tuning *iq; iq = malloc(sizeof *iq); if (iq == NULL) return NULL; iq->isp = isp; iq->frame_count = 0; iq->pix_max = (1 << 10) - 1; iq->mean_level = 0.15; iq->exposure = 1000; iq->exposure_min = 10; iq->exposure_max = 2000; iq->gain = 8; iq->gain_min = 8; iq->gain_max = 1024; iq->black_level = 64; omap3_isp_sensor_set_gain(isp, iq->gain); omap3_isp_sensor_set_exposure(isp, iq->exposure); omap3_isp_ccdc_set_black_level(isp, iq->black_level); omap3_isp_stats_get_format(isp, &format); window.left = 0; window.top = 0; window.width = format.width; window.height = format.height; omap3_isp_aewb_configure(isp, &window, iq->pix_max - iq->black_level - 1); omap3_isp_stats_enable(isp, true); return iq; } void iq_cleanup(struct iq_tuning *iq) { free(iq); }