From: Balakrishnan Sambath Replace simple min/max detection with smart outlier rejection that skips bottom/top 2% of histogram to avoid noise and saturation. Add channel average calculation using weighted pixel intensity instead of simple pixel counting for more accurate color analysis. Signed-off-by: Balakrishnan Sambath --- .../platform/microchip/microchip-isc-base.c | 83 ++++++++++++++++--- .../media/platform/microchip/microchip-isc.h | 2 + 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/microchip/microchip-isc-base.c b/drivers/media/platform/microchip/microchip-isc-base.c index c138e92a1aca..956bdea830e3 100644 --- a/drivers/media/platform/microchip/microchip-isc-base.c +++ b/drivers/media/platform/microchip/microchip-isc-base.c @@ -262,6 +262,10 @@ static void isc_set_histogram(struct isc_device *isc, bool enable) struct isc_ctrls *ctrls = &isc->ctrls; if (enable) { + /* Initialize histogram data storage for clean start */ + memset(ctrls->total_pixels, 0, sizeof(ctrls->total_pixels)); + memset(ctrls->hist_minmax, 0, sizeof(ctrls->hist_minmax)); + regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his, ISC_HIS_CFG_MODE_GR | (isc->config.sd_format->cfa_baycfg @@ -1231,24 +1235,83 @@ static void isc_hist_count(struct isc_device *isc, u32 *min, u32 *max) regmap_bulk_read(regmap, ISC_HIS_ENTRY + isc->offsets.his_entry, hist_entry, HIST_ENTRIES); - *hist_count = 0; - /* - * we deliberately ignore the end of the histogram, - * the most white pixels - */ + /* Calculate total pixels */ + u32 total_pixels = 0; + + for (i = 0; i < HIST_ENTRIES; i++) + total_pixels += hist_entry[i]; + + /* Handle empty histogram case */ + if (total_pixels == 0) { + *hist_count = 0; + ctrls->channel_avg[ctrls->hist_id] = 256; /* Default middle value */ + ctrls->total_pixels[ctrls->hist_id] = 0; + *min = 1; + *max = HIST_ENTRIES - 1; + dev_dbg(isc->dev, "isc wb: no pixels in histogram for channel %u", ctrls->hist_id); + return; + } + + /* Smart outlier rejection - skip bottom/top 2% */ + u32 dark_threshold = total_pixels / 50; /* Bottom 2% */ + u32 bright_threshold = total_pixels / 50; /* Top 2% */ + u32 cumulative = 0; + + /* Find effective minimum (skip dark noise) */ + *min = 1; for (i = 1; i < HIST_ENTRIES; i++) { - if (*hist_entry && !*min) + cumulative += hist_entry[i]; + if (cumulative > dark_threshold) { *min = i; - if (*hist_entry) + break; + } + } + + /* Find effective maximum (skip bright saturation) */ + cumulative = 0; + *max = HIST_ENTRIES - 1; + for (i = HIST_ENTRIES - 1; i > *min; i--) { + cumulative += hist_entry[i]; + if (cumulative > bright_threshold) { *max = i; - *hist_count += i * (*hist_entry++); + break; + } } + /* Ensure reasonable range */ + if (*max <= *min) { + *min = HIST_ENTRIES / 4; + *max = (HIST_ENTRIES * 3) / 4; + } + + /* Calculate both pixel count and weighted average for useful range */ + *hist_count = 0; + u64 weighted_sum = 0; + + for (i = *min; i <= *max; i++) { + u32 pixel_count = hist_entry[i]; + *hist_count += pixel_count; + weighted_sum += (u64)i * pixel_count; + } + + /* Store total useful pixels for this channel */ + ctrls->total_pixels[ctrls->hist_id] = *hist_count; + + /* Calculate channel average */ + if (*hist_count > 0) + ctrls->channel_avg[ctrls->hist_id] = + div64_u64(weighted_sum, *hist_count); + else + /* Default middle value */ + ctrls->channel_avg[ctrls->hist_id] = 256; + if (!*min) *min = 1; - dev_dbg(isc->dev, "isc wb: hist_id %u, hist_count %u", - ctrls->hist_id, *hist_count); + dev_dbg(isc->dev, + "isc wb: hist_id %u, avg %u, count %u, range [%u,%u], total %u", + ctrls->hist_id, ctrls->channel_avg[ctrls->hist_id], + *hist_count, *min, *max, total_pixels); } static void isc_wb_update(struct isc_ctrls *ctrls) diff --git a/drivers/media/platform/microchip/microchip-isc.h b/drivers/media/platform/microchip/microchip-isc.h index ad4e98a1dd8f..bd75ff4f109b 100644 --- a/drivers/media/platform/microchip/microchip-isc.h +++ b/drivers/media/platform/microchip/microchip-isc.h @@ -156,6 +156,8 @@ struct isc_ctrls { #define HIST_MIN_INDEX 0 #define HIST_MAX_INDEX 1 u32 hist_minmax[HIST_BAYER][2]; + u32 channel_avg[HIST_BAYER]; /* Average pixel intensity per channel */ + u32 total_pixels[HIST_BAYER]; /* Total pixels per channel */ }; #define ISC_PIPE_LINE_NODE_NUM 15 -- 2.34.1