diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-06-22 11:45:24 +0300 |
---|---|---|
committer | Erik Gilling <konkers@android.com> | 2011-07-18 16:03:51 -0700 |
commit | a2ba11ee2fd67aa346610687288337e0827da2b1 (patch) | |
tree | b2b9bf26bf3e5ffb42b86f8f876fae21277b824a | |
parent | 2de1312397d169b871473f3da1db38b5cdd3d784 (diff) | |
download | kernel_samsung_tuna-a2ba11ee2fd67aa346610687288337e0827da2b1.zip kernel_samsung_tuna-a2ba11ee2fd67aa346610687288337e0827da2b1.tar.gz kernel_samsung_tuna-a2ba11ee2fd67aa346610687288337e0827da2b1.tar.bz2 |
OMAP: DSS2: Add Color Phase Rotation support
Add Color Phase Rotation (CPR) support and sysfs files to enable CPR and
to set the CPR coefficient matrix.
CPR is enabled via manager?/cpr_enable file, and the coefficient matrix
is set via manager?/cpr_coef file. The values in cpr_coef are in the
following order:
RR RG RB GR GG GB BR BG BB
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 34 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.h | 3 | ||||
-rw-r--r-- | drivers/video/omap2/dss/manager.c | 119 | ||||
-rw-r--r-- | include/video/omapdss.h | 9 |
4 files changed, 165 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 9681717..d6554cd 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1080,6 +1080,40 @@ void dispc_enable_zorder(enum omap_plane plane, bool enable) dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); } +void dispc_enable_cpr(enum omap_channel channel, bool enable) +{ + u16 reg; + + if (channel == OMAP_DSS_CHANNEL_LCD) + reg = DISPC_CONFIG; + else if (channel == OMAP_DSS_CHANNEL_LCD2) + reg = DISPC_CONFIG2; + else + return; + + REG_FLD_MOD(reg, enable, 15, 15); +} + +void dispc_set_cpr_coef(enum omap_channel channel, + struct omap_dss_cpr_coefs *coefs) +{ + u32 coef_r, coef_g, coef_b; + + if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2) + return; + + coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) | + FLD_VAL(coefs->rb, 9, 0); + coef_g = FLD_VAL(coefs->gr, 31, 22) | FLD_VAL(coefs->gg, 20, 11) | + FLD_VAL(coefs->gb, 9, 0); + coef_b = FLD_VAL(coefs->br, 31, 22) | FLD_VAL(coefs->bg, 20, 11) | + FLD_VAL(coefs->bb, 9, 0); + + dispc_write_reg(DISPC_CPR_COEF_R(channel), coef_r); + dispc_write_reg(DISPC_CPR_COEF_G(channel), coef_g); + dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b); +} + static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) { u32 val; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 6d59b26..9cf1626 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -401,6 +401,9 @@ void dispc_set_burst_size(enum omap_plane plane, void dispc_set_zorder(enum omap_plane plane, enum omap_overlay_zorder zorder); void dispc_enable_zorder(enum omap_plane plane, bool enable); +void dispc_enable_cpr(enum omap_channel channel, bool enable); +void dispc_set_cpr_coef(enum omap_channel channel, + struct omap_dss_cpr_coefs *coefs); void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr); void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr); diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 106767d..a9b51d0 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -279,6 +279,108 @@ static ssize_t manager_alpha_blending_enabled_store( return size; } +static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.cpr_enable); +} + +static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr, + const char *buf, size_t size) +{ + struct omap_overlay_manager_info info; + int v; + int r; + bool enable; + + if (!dss_has_feature(FEAT_CPR)) + return -ENODEV; + + r = kstrtoint(buf, 0, &v); + if (r) + return r; + + enable = !!v; + + mgr->get_manager_info(mgr, &info); + + if (info.cpr_enable == enable) + return size; + + info.cpr_enable = enable; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + if (r) + return r; + + return size; +} + +static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr, + char *buf) +{ + struct omap_overlay_manager_info info; + + mgr->get_manager_info(mgr, &info); + + return snprintf(buf, PAGE_SIZE, + "%d %d %d %d %d %d %d %d %d\n", + info.cpr_coefs.rr, + info.cpr_coefs.rg, + info.cpr_coefs.rb, + info.cpr_coefs.gr, + info.cpr_coefs.gg, + info.cpr_coefs.gb, + info.cpr_coefs.br, + info.cpr_coefs.bg, + info.cpr_coefs.bb); +} + +static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr, + const char *buf, size_t size) +{ + struct omap_overlay_manager_info info; + struct omap_dss_cpr_coefs coefs; + int r, i; + s16 *arr; + + if (!dss_has_feature(FEAT_CPR)) + return -ENODEV; + + if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd", + &coefs.rr, &coefs.rg, &coefs.rb, + &coefs.gr, &coefs.gg, &coefs.gb, + &coefs.br, &coefs.bg, &coefs.bb) != 9) + return -EINVAL; + + arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb, + coefs.gr, coefs.gg, coefs.gb, + coefs.br, coefs.bg, coefs.bb }; + + for (i = 0; i < 9; ++i) { + if (arr[i] < -512 || arr[i] > 511) + return -EINVAL; + } + + mgr->get_manager_info(mgr, &info); + + info.cpr_coefs = coefs; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + if (r) + return r; + + return size; +} + struct manager_attribute { struct attribute attr; ssize_t (*show)(struct omap_overlay_manager *, char *); @@ -304,6 +406,12 @@ static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, manager_alpha_blending_enabled_show, manager_alpha_blending_enabled_store); +static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR, + manager_cpr_enable_show, + manager_cpr_enable_store); +static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR, + manager_cpr_coef_show, + manager_cpr_coef_store); static struct attribute *manager_sysfs_attrs[] = { @@ -314,6 +422,8 @@ static struct attribute *manager_sysfs_attrs[] = { &manager_attr_trans_key_value.attr, &manager_attr_trans_key_enabled.attr, &manager_attr_alpha_blending_enabled.attr, + &manager_attr_cpr_enable.attr, + &manager_attr_cpr_coef.attr, NULL }; @@ -472,6 +582,9 @@ struct manager_cache_data { bool enlarge_update_area; struct callback_states cb; /* callback data for the last 3 states */ + + bool cpr_enable; + struct omap_dss_cpr_coefs cpr_coefs; }; static struct { @@ -982,6 +1095,10 @@ static void configure_manager(enum omap_channel channel) } else { dispc_enable_alpha_blending(channel, c->alpha_enabled); } + if (dss_has_feature(FEAT_CPR)) { + dispc_enable_cpr(channel, c->cpr_enable); + dispc_set_cpr_coef(channel, &c->cpr_coefs); + } } /* configure_dispc() tries to write values from cache to shadow registers. @@ -1574,6 +1691,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) mc->trans_key = mgr->info.trans_key; mc->trans_enabled = mgr->info.trans_enabled; mc->alpha_enabled = mgr->info.alpha_enabled; + mc->cpr_coefs = mgr->info.cpr_coefs; + mc->cpr_enable = mgr->info.cpr_enable; mc->manual_upd_display = dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 565a49b..5e06a73 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -337,6 +337,12 @@ struct omapdss_ovl_cb { void *data; }; +struct omap_dss_cpr_coefs { + s16 rr, rg, rb; + s16 gr, gg, gb; + s16 br, bg, bb; +}; + struct omap_overlay_info { bool enabled; @@ -402,6 +408,9 @@ struct omap_overlay_manager_info { bool alpha_enabled; struct omapdss_ovl_cb cb; + + bool cpr_enable; + struct omap_dss_cpr_coefs cpr_coefs; }; struct omap_overlay_manager { |