/* Periodic update */ bool nvsd_update_brightness(struct tegra_dc *dc) { u32 val = 0; int cur_sd_brightness; if (sd_brightness) { if (atomic_read(&man_k_until_blank)) { val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL); val &= ~SD_CORRECTION_MODE_MAN; tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL); atomic_set(&man_k_until_blank, 0); } cur_sd_brightness = atomic_read(sd_brightness); /* read brightness value */ val = tegra_dc_readl(dc, DC_DISP_SD_BL_CONTROL); val = SD_BLC_BRIGHTNESS(val); if (val != (u32)cur_sd_brightness) { /* set brightness value and note the update */ atomic_set(sd_brightness, (int)val); return true; } } /* No update needed. */ return false; }
static bool nvsd_phase_in_adjustments(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings) { u8 step, cur_sd_brightness; u16 target_k, cur_k; u32 man_k, val; cur_sd_brightness = atomic_read(_sd_brightness); target_k = tegra_dc_readl(dc, DC_DISP_SD_HW_K_VALUES); target_k = SD_HW_K_R(target_k); cur_k = tegra_dc_readl(dc, DC_DISP_SD_MAN_K_VALUES); cur_k = SD_HW_K_R(cur_k); /* read brightness value */ val = tegra_dc_readl(dc, DC_DISP_SD_BL_CONTROL); val = SD_BLC_BRIGHTNESS(val); step = settings->phase_adj_step; if (cur_sd_brightness != val || target_k != cur_k) { if (!step) step = ADJ_PHASE_STEP; /* Phase in Backlight and Pixel K every ADJ_PHASE_STEP frames*/ if ((step-- & ADJ_PHASE_STEP) == ADJ_PHASE_STEP) { if (val != cur_sd_brightness) { val > cur_sd_brightness ? (cur_sd_brightness++) : (cur_sd_brightness--); } if (target_k != cur_k) { if (target_k > cur_k) cur_k += K_STEP; else cur_k -= K_STEP; } /* Set manual k value */ man_k = SD_MAN_K_R(cur_k) | SD_MAN_K_G(cur_k) | SD_MAN_K_B(cur_k); tegra_dc_io_start(dc); tegra_dc_writel(dc, man_k, DC_DISP_SD_MAN_K_VALUES); tegra_dc_io_end(dc); /* Set manual brightness value */ atomic_set(_sd_brightness, cur_sd_brightness); } settings->phase_adj_step = step; return true; } else return false; }
/* Periodic update */ bool nvsd_update_brightness(struct tegra_dc *dc) { u32 val = 0; int cur_sd_brightness; struct tegra_dc_sd_settings *settings = dc->out->sd_settings; if (sd_brightness) { if (atomic_read(&man_k_until_blank) && !settings->phase_in_adjustments) { val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL); val &= ~SD_CORRECTION_MODE_MAN; tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL); atomic_set(&man_k_until_blank, 0); } if (settings->cmd) nvsd_cmd_handler(settings, dc); /* nvsd_cmd_handler may turn off didim */ if (!settings->enable) return true; cur_sd_brightness = atomic_read(sd_brightness); /* read brightness value */ val = tegra_dc_readl(dc, DC_DISP_SD_BL_CONTROL); val = SD_BLC_BRIGHTNESS(val); if (settings->phase_in_adjustments) { return nvsd_phase_in_adjustments(dc, settings); } else if (val != (u32)cur_sd_brightness) { /* set brightness value and note the update */ atomic_set(sd_brightness, (int)val); return true; } } /* No update needed. */ return false; }
static bool nvsd_phase_in_adjustments(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings) { u8 step, cur_sd_brightness; int commanded; u16 target_k, cur_k; u32 man_k, val; struct platform_device *pdev; struct backlight_device *bl; bool below_min_brightness = false; cur_sd_brightness = atomic_read(sd_brightness); target_k = tegra_dc_readl(dc, DC_DISP_SD_HW_K_VALUES); target_k = SD_HW_K_R(target_k); cur_k = tegra_dc_readl(dc, DC_DISP_SD_MAN_K_VALUES); cur_k = SD_HW_K_R(cur_k); /* read brightness value */ val = tegra_dc_readl(dc, DC_DISP_SD_BL_CONTROL); val = SD_BLC_BRIGHTNESS(val); if (settings->panel_min_brightness) { pdev = settings->bl_device; bl = platform_get_drvdata(pdev); commanded = (cur_sd_brightness * bl->props.brightness) / 255; /* Need to reduce how aggressive we are */ if (commanded < settings->panel_min_brightness) { if (cur_k || cur_sd_brightness != 255) below_min_brightness = true; else return false; } /* Return so we don't modify in the opposite direction */ if (commanded == settings->panel_min_brightness && target_k > cur_k) return false; } /* Correct until brightness is high enough */ if (below_min_brightness) { if (cur_sd_brightness != 255) cur_sd_brightness++; if (cur_k) cur_k -= K_STEP; man_k = SD_MAN_K_R(cur_k) | SD_MAN_K_G(cur_k) | SD_MAN_K_B(cur_k); tegra_dc_writel(dc, man_k, DC_DISP_SD_MAN_K_VALUES); atomic_set(sd_brightness, cur_sd_brightness); return true; } step = settings->phase_adj_step; if (cur_sd_brightness != val || target_k != cur_k) { if (!step) step = ADJ_PHASE_STEP; /* Phase in Backlight and Pixel K every ADJ_PHASE_STEP frames*/ if ((step-- & ADJ_PHASE_STEP) == ADJ_PHASE_STEP) { if (val != cur_sd_brightness) { val > cur_sd_brightness ? (cur_sd_brightness++) : (cur_sd_brightness--); } if (target_k != cur_k) { if (target_k > cur_k) cur_k += K_STEP; else cur_k -= K_STEP; } /* Set manual k value */ man_k = SD_MAN_K_R(cur_k) | SD_MAN_K_G(cur_k) | SD_MAN_K_B(cur_k); tegra_dc_writel(dc, man_k, DC_DISP_SD_MAN_K_VALUES); /* Set manual brightness value */ atomic_set(sd_brightness, cur_sd_brightness); } settings->phase_adj_step = step; return true; } else return false; }
/* Periodic update */ bool nvsd_update_brightness(struct tegra_dc *dc) { u32 val = 0; int cur_sd_brightness; int sw_sd_brightness; struct tegra_dc_sd_settings *settings = dc->out->sd_settings; bool nvsd_updated = false; if (_sd_brightness) { if (atomic_read(&man_k_until_blank) && !settings->phase_in_adjustments) { val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL); val &= ~SD_CORRECTION_MODE_MAN; tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL); atomic_set(&man_k_until_blank, 0); } if (settings->cmd) nvsd_cmd_handler(settings, dc); /* nvsd_cmd_handler may turn off didim */ if (!settings->enable) return true; cur_sd_brightness = atomic_read(_sd_brightness); /* read brightness value */ val = tegra_dc_readl(dc, DC_DISP_SD_BL_CONTROL); val = SD_BLC_BRIGHTNESS(val); /* PRISM is updated by hw or sw algorithm. Brightness is * compensated according to histogram for soft-clipping * if hw output is used to update brightness. */ if (settings->phase_in_adjustments) { nvsd_updated = nvsd_phase_in_adjustments(dc, settings); } else if (settings->soft_clipping_enable && settings->soft_clipping_correction) { sw_sd_brightness = nvsd_set_brightness(dc); if (sw_sd_brightness != cur_sd_brightness) { atomic_set(_sd_brightness, sw_sd_brightness); nvsd_updated = true; } } else if (val != (u32)cur_sd_brightness) { /* set brightness value and note the update */ atomic_set(_sd_brightness, (int)val); nvsd_updated = true; } if (nvsd_updated) { smooth_k_frames_left = smooth_k_duration_frames; return true; } if (settings->smooth_k_enable) { if (smooth_k_frames_left--) return true; else smooth_k_frames_left = smooth_k_duration_frames; } } /* No update needed. */ return false; }