[PATCH 2/4] drm/omapdrm: Add gamma table support to DSS dispc
Tomi Valkeinen
tomi.valkeinen at ti.com
Fri May 20 12:51:52 UTC 2016
Hi,
On 20/05/16 09:35, Jyri Sarha wrote:
> Add gamma table support to DSS dispc.
>
> DSS driver initializes the default gamma table at component bind time
> and holds a copy of all gamma tables in it's internal data structure.
"its"
> Each call to dispc_mgr_set_gamma() updates the internal table and
> triggers write the HW, if it is enabled. The tables are restored to HW
"... to the HW"?
> in PM resume callback. The tables at DSS side matches the HW tables in
> size and in number of significant bits per color component. The
Maybe "the tables in RAM match the tables in HW".
> dispc_mgr_set_gamma() converts the size of any given table to match
> the table size in HW.
>
> dispc_mgr_gamma_size() gives HW gamma table size for the channel
> and returns 0 if gamma table is not supported by HW or DSS driver.
>
> Signed-off-by: Jyri Sarha <jsarha at ti.com>
> ---
> drivers/gpu/drm/omapdrm/dss/dispc.c | 189 ++++++++++++++++++++++++++---
> drivers/gpu/drm/omapdrm/dss/dispc.h | 5 +
> drivers/gpu/drm/omapdrm/dss/dss_features.c | 2 +
> drivers/gpu/drm/omapdrm/dss/dss_features.h | 1 +
> drivers/gpu/drm/omapdrm/dss/hdmi4.c | 3 -
> drivers/gpu/drm/omapdrm/dss/hdmi5.c | 3 -
> drivers/gpu/drm/omapdrm/dss/omapdss.h | 5 +
> 7 files changed, 186 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
> index f83608b..87dde05 100644
> --- a/drivers/gpu/drm/omapdrm/dss/dispc.c
> +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
> @@ -116,6 +116,7 @@ struct dispc_features {
> };
>
> #define DISPC_MAX_NR_FIFOS 5
> +#define DISPC_MAX_CHANNEL_GAMMA 4
>
> static struct {
> struct platform_device *pdev;
> @@ -135,6 +136,8 @@ static struct {
> bool ctx_valid;
> u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
>
> + u32 *gamma_table[DISPC_MAX_CHANNEL_GAMMA];
> +
> const struct dispc_features *feat;
>
> bool is_enabled;
> @@ -178,11 +181,19 @@ struct dispc_reg_field {
> u8 low;
> };
>
> +struct dispc_gamma_desc {
> + u32 len;
> + u32 bits;
> + u16 reg;
> + bool has_index;
> +};
> +
> static const struct {
> const char *name;
> u32 vsync_irq;
> u32 framedone_irq;
> u32 sync_lost_irq;
> + struct dispc_gamma_desc gamma;
> struct dispc_reg_field reg_desc[DISPC_MGR_FLD_NUM];
> } mgr_desc[] = {
> [OMAP_DSS_CHANNEL_LCD] = {
> @@ -190,6 +201,12 @@ static const struct {
> .vsync_irq = DISPC_IRQ_VSYNC,
> .framedone_irq = DISPC_IRQ_FRAMEDONE,
> .sync_lost_irq = DISPC_IRQ_SYNC_LOST,
> + .gamma = {
> + .len = 256,
> + .bits = 8,
> + .reg = DISPC_GAMMA_TABLE0,
> + .has_index = true,
> + },
> .reg_desc = {
> [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 0, 0 },
> [DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL, 3, 3 },
> @@ -207,6 +224,12 @@ static const struct {
> .vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
> .framedone_irq = DISPC_IRQ_FRAMEDONETV,
> .sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT,
> + .gamma = {
> + .len = 1024,
> + .bits = 10,
> + .reg = DISPC_GAMMA_TABLE2,
> + .has_index = false,
> + },
> .reg_desc = {
> [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 },
> [DISPC_MGR_FLD_STNTFT] = { },
> @@ -224,6 +247,12 @@ static const struct {
> .vsync_irq = DISPC_IRQ_VSYNC2,
> .framedone_irq = DISPC_IRQ_FRAMEDONE2,
> .sync_lost_irq = DISPC_IRQ_SYNC_LOST2,
> + .gamma = {
> + .len = 256,
> + .bits = 8,
> + .reg = DISPC_GAMMA_TABLE1,
> + .has_index = true,
> + },
> .reg_desc = {
> [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL2, 0, 0 },
> [DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL2, 3, 3 },
> @@ -241,6 +270,12 @@ static const struct {
> .vsync_irq = DISPC_IRQ_VSYNC3,
> .framedone_irq = DISPC_IRQ_FRAMEDONE3,
> .sync_lost_irq = DISPC_IRQ_SYNC_LOST3,
> + .gamma = {
> + .len = 256,
> + .bits = 8,
> + .reg = DISPC_GAMMA_TABLE3,
> + .has_index = true,
> + },
> .reg_desc = {
> [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL3, 0, 0 },
> [DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL3, 3, 3 },
> @@ -1084,20 +1119,6 @@ static u32 dispc_ovl_get_burst_size(enum omap_plane plane)
> return unit * 8;
> }
>
> -void dispc_enable_gamma_table(bool enable)
> -{
> - /*
> - * This is partially implemented to support only disabling of
> - * the gamma table.
> - */
> - if (enable) {
> - DSSWARN("Gamma table enabling for TV not yet supported");
> - return;
> - }
> -
> - REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
> -}
> -
> static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
> {
> if (channel == OMAP_DSS_CHANNEL_DIGIT)
> @@ -3814,6 +3835,128 @@ void dispc_disable_sidle(void)
> REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
> }
>
> +u32 dispc_mgr_gamma_size(enum omap_channel channel)
> +{
> + const struct dispc_gamma_desc *gdesc = &mgr_desc[channel].gamma;
> +
> + if (!dss_has_feature(FEAT_GAMMA_TABLE))
> + return 0;
> +
This should probably check the availability of LCD2/LCD3?
> + return gdesc->len;
> +}
> +EXPORT_SYMBOL(dispc_mgr_gamma_size);
> +
> +static void dispc_mgr_write_gamma_table(enum omap_channel channel)
> +{
> + const struct dispc_gamma_desc *gdesc = &mgr_desc[channel].gamma;
> + u32 *table = dispc.gamma_table[channel];
> + unsigned int i;
> +
> + DSSDBG("%s: channel %d\n", __func__, channel);
> +
> + for (i = 0; i < gdesc->len; ++i) {
> + u32 v = table[i];
> +
> + if (gdesc->has_index)
> + v |= i << 24;
> + else if (i == 0)
> + v |= 1 << 31;
> +
> + dispc_write_reg(gdesc->reg, v);
> + }
> +}
> +
> +static void dispc_restore_gamma_tables(void)
> +{
> + DSSDBG("%s()\n", __func__);
> +
> + if (!dss_has_feature(FEAT_GAMMA_TABLE))
> + return;
> +
> + dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD);
> +
> + dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_DIGIT);
> +
> + if (dss_has_feature(FEAT_MGR_LCD2))
> + dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD2);
> +
> + if (dss_has_feature(FEAT_MGR_LCD3))
> + dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD3);
> +}
> +
> +void dispc_mgr_set_gamma(enum omap_channel channel,
> + const struct drm_color_lut *lut,
> + unsigned int length)
> +{
> + const struct dispc_gamma_desc *gdesc = &mgr_desc[channel].gamma;
> + u32 *table = dispc.gamma_table[channel];
> + int i;
unsigned.
> +
> + DSSDBG("%s: channel %d, lut len %u, hw len %u\n", __func__,
> + channel, length, gdesc->len);
> +
> + if (!dss_has_feature(FEAT_GAMMA_TABLE))
> + return;
> +
> + for (i = 0; i < length; ++i) {
> + int first = i * (gdesc->len - 1) / (length - 1);
> + int last = (i + 1) * (gdesc->len - 1) / (length - 1);
This might be slightly more readable if you hade src_len and dst_len
local variables. Or maybe it's clear enough, it's a short function.
> + int w = last - first;
unsigned.
> + u16 r, g, b;
> + int j;
unsigned.
> +
> + for (j = 0; j <= w; j++) {
> + r = (lut[i].red * (w - j) + lut[i+1].red * j) / w;
> + g = (lut[i].green * (w - j) + lut[i+1].green * j) / w;
> + b = (lut[i].blue * (w - j) + lut[i+1].blue * j) / w;
> +
> + r >>= (16 - gdesc->bits);
> + g >>= (16 - gdesc->bits);
> + b >>= (16 - gdesc->bits);
I don't think the parenthesis do anything here.
> +
> + table[first + j] = (r << (gdesc->bits * 2)) |
> + (g << gdesc->bits) | b;
> + }
> + }
> +
> + if (dispc.is_enabled)
> + dispc_mgr_write_gamma_table(channel);
> +}
> +EXPORT_SYMBOL(dispc_mgr_set_gamma);
> +
> +static int dispc_init_gamma_tables(void)
> +{
> + int channel;
> +
> + if (!dss_has_feature(FEAT_GAMMA_TABLE))
> + return;
> +
> + for (channel = 0; channel < ARRAY_SIZE(dispc.gamma_table); channel++) {
> + const struct dispc_gamma_desc *gdesc = &mgr_desc[channel].gamma;
> + u32 *table;
> + int i;
unsigned.
> +
> + if (channel == OMAP_DSS_CHANNEL_LCD2 &&
> + !dss_has_feature(FEAT_MGR_LCD2))
> + continue;
> +
> + if (channel == OMAP_DSS_CHANNEL_LCD3 &&
> + !dss_has_feature(FEAT_MGR_LCD3))
> + continue;
> +
> + table = devm_kmalloc_array(&dispc.pdev->dev, gdesc->len,
> + sizeof(table[i]), GFP_KERNEL);
Wouldn't allocating gdesc->len * sizeof(u32) be much more
understandable? 'i' is even uninitialized at this point, making the code
quite suspicious.
> + if (!table)
> + return -ENOMEM;
> +
> + for (i = 0; i < gdesc->len; ++i)
> + table[i] =
> + (i << 2*gdesc->bits) | (i << gdesc->bits) | i;
Add an empty line here.
Add spaces around '*'.
And instead of splitting the line above, perhaps assign the value to u32
local, and assign that to table[i].
> + dispc.gamma_table[channel] = table;
> + }
> + return 0;
> +}
> +
> static void _omap_dispc_initial_config(void)
> {
> u32 l;
> @@ -3829,8 +3972,16 @@ static void _omap_dispc_initial_config(void)
> dispc.core_clk_rate = dispc_fclk_rate();
> }
>
> - /* FUNCGATED */
> - if (dss_has_feature(FEAT_FUNCGATED))
> + /* Use gamma table */
Use gamma table for what, instead of what?
> + if (dss_has_feature(FEAT_GAMMA_TABLE))
> + REG_FLD_MOD(DISPC_CONFIG, 1, 3, 3);
> +
> + /* For older DSS versions (FEAT_FUNCGATED) this enables
> + * func-clock auto-gating. For newer versions
> + * (FEAT_GAMMA_TABLE) this enables tv-out gamma tables.
> + */
> + if (dss_has_feature(FEAT_FUNCGATED) ||
> + dss_has_feature(FEAT_GAMMA_TABLE))
> REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
>
> dispc_setup_color_conv_coef();
> @@ -4100,6 +4251,10 @@ static int dispc_bind(struct device *dev, struct device *master, void *data)
> }
> }
>
> + r = dispc_init_gamma_tables();
> + if (r)
> + return r;
> +
> pm_runtime_enable(&pdev->dev);
>
> r = dispc_runtime_get();
> @@ -4170,6 +4325,8 @@ static int dispc_runtime_resume(struct device *dev)
> _omap_dispc_initial_config();
>
> dispc_restore_context();
> +
> + dispc_restore_gamma_tables();
> }
>
> dispc.is_enabled = true;
> diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.h b/drivers/gpu/drm/omapdrm/dss/dispc.h
> index 4837442..bc1d812 100644
> --- a/drivers/gpu/drm/omapdrm/dss/dispc.h
> +++ b/drivers/gpu/drm/omapdrm/dss/dispc.h
> @@ -42,6 +42,11 @@
> #define DISPC_MSTANDBY_CTRL 0x0858
> #define DISPC_GLOBAL_MFLAG_ATTRIBUTE 0x085C
>
> +#define DISPC_GAMMA_TABLE0 0x0630
> +#define DISPC_GAMMA_TABLE1 0x0634
> +#define DISPC_GAMMA_TABLE2 0x0638
> +#define DISPC_GAMMA_TABLE3 0x0850
> +
> /* DISPC overlay registers */
> #define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \
> DISPC_BA0_OFFSET(n))
> diff --git a/drivers/gpu/drm/omapdrm/dss/dss_features.c b/drivers/gpu/drm/omapdrm/dss/dss_features.c
> index c886a29..f77b1c5 100644
> --- a/drivers/gpu/drm/omapdrm/dss/dss_features.c
> +++ b/drivers/gpu/drm/omapdrm/dss/dss_features.c
> @@ -593,6 +593,7 @@ static const enum dss_feat_id omap4_dss_feat_list[] = {
> FEAT_ALPHA_FREE_ZORDER,
> FEAT_FIFO_MERGE,
> FEAT_BURST_2D,
> + FEAT_GAMMA_TABLE,
> };
The dss_features is deprecated. New features should be added to the
respective driver. In this case, dispc.c. See struct dispc_features.
Tomi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160520/c065ae3d/attachment-0001.sig>
More information about the dri-devel
mailing list