[PATCH] MAINTAINERS: Add Mihail to Komeda DRM driver

2019-10-21 Thread Mihail Atanassov
I'll be the main point of contact.

Cc: James Qian Wang (Arm Technology China) 
Cc: Liviu Dudau 
Signed-off-by: Mihail Atanassov 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 94fb077c0817..d32f263f0022 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1251,6 +1251,7 @@ F:
Documentation/devicetree/bindings/display/arm,hdlcd.txt
 ARM KOMEDA DRM-KMS DRIVER
 M: James (Qian) Wang 
 M: Liviu Dudau 
+M: Mihail Atanassov 
 L: Mali DP Maintainers 
 S: Supported
 T: git git://anongit.freedesktop.org/drm/drm-misc
-- 
2.23.0



Re: drm/komeda: Dump SC_ENH_* registers from scaler block

2019-10-21 Thread Mihail Atanassov
On Wednesday, 16 October 2019 09:17:39 BST james qian wang (Arm Technology 
China) wrote:
> On Tue, Oct 15, 2019 at 11:00:01AM +0000, Mihail Atanassov wrote:
> > Signed-off-by: Mihail Atanassov 
> > ---
> >  .../gpu/drm/arm/display/komeda/d71/d71_component.c | 14 +-
> >  1 file changed, 13 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c 
> > b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
> > index c3d29c0b051b..7252fc387fba 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
> > +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
> > @@ -703,7 +703,7 @@ static void d71_scaler_update(struct komeda_component 
> > *c,
> >  
> >  static void d71_scaler_dump(struct komeda_component *c, struct seq_file 
> > *sf)
> >  {
> > -   u32 v[9];
> > +   u32 v[10];
> >  
> > dump_block_header(sf, c->reg);
> >  
> > @@ -723,6 +723,18 @@ static void d71_scaler_dump(struct komeda_component 
> > *c, struct seq_file *sf)
> > seq_printf(sf, "SC_H_DELTA_PH:\t\t0x%X\n", v[6]);
> > seq_printf(sf, "SC_V_INIT_PH:\t\t0x%X\n", v[7]);
> > seq_printf(sf, "SC_V_DELTA_PH:\t\t0x%X\n", v[8]);
> > +
> > +   get_values_from_reg(c->reg, 0x130, 10, v);
> > +   seq_printf(sf, "SC_ENH_LIMITS:\t\t0x%X\n", v[0]);
> > +   seq_printf(sf, "SC_ENH_COEFF0:\t\t0x%X\n", v[1]);
> > +   seq_printf(sf, "SC_ENH_COEFF1:\t\t0x%X\n", v[2]);
> > +   seq_printf(sf, "SC_ENH_COEFF2:\t\t0x%X\n", v[3]);
> > +   seq_printf(sf, "SC_ENH_COEFF3:\t\t0x%X\n", v[4]);
> > +   seq_printf(sf, "SC_ENH_COEFF4:\t\t0x%X\n", v[5]);
> > +   seq_printf(sf, "SC_ENH_COEFF5:\t\t0x%X\n", v[6]);
> > +   seq_printf(sf, "SC_ENH_COEFF6:\t\t0x%X\n", v[7]);
> > +   seq_printf(sf, "SC_ENH_COEFF7:\t\t0x%X\n", v[8]);
> > +   seq_printf(sf, "SC_ENH_COEFF8:\t\t0x%X\n", v[9]);
> >  }
> >
> 
> Looks good to me.
> 
> Reviewed-by: James Qian Wang (Arm Technology China) 

Thanks, applied to drm-misc-next - 
2b6f5883edcc47ef6146832112a0125810d28f78.

> 
> >  static const struct komeda_component_funcs d71_scaler_funcs = {
> 


-- 
Mihail





Re: [PATCH v2 1/4] drm: Add a new helper drm_color_ctm_s31_32_to_qm_n()

2019-10-11 Thread Mihail Atanassov
Hi James,

On Friday, 11 October 2019 06:45:27 BST james qian wang (Arm Technology China) 
wrote:
> Add a new helper function drm_color_ctm_s31_32_to_qm_n() for driver to
> convert S31.32 sign-magnitude to Qm.n 2's complement that supported by
> hardware.
> 
> Signed-off-by: james qian wang (Arm Technology China) 
> 
> ---
>  drivers/gpu/drm/drm_color_mgmt.c | 23 +++
>  include/drm/drm_color_mgmt.h |  2 ++
>  2 files changed, 25 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_color_mgmt.c 
> b/drivers/gpu/drm/drm_color_mgmt.c
> index 4ce5c6d8de99..3d533d0b45af 100644
> --- a/drivers/gpu/drm/drm_color_mgmt.c
> +++ b/drivers/gpu/drm/drm_color_mgmt.c
> @@ -132,6 +132,29 @@ uint32_t drm_color_lut_extract(uint32_t user_input, 
> uint32_t bit_precision)
>  }
>  EXPORT_SYMBOL(drm_color_lut_extract);
> 
> +/**
> + * drm_color_ctm_s31_32_to_qm_n
> + *
> + * @user_input: input value
> + * @m: number of integer bits
> + * @n: number of fractinal bits
> + *
> + * Convert and clamp S31.32 sign-magnitude to Qm.n 2's complement.
> + */
> +uint64_t drm_color_ctm_s31_32_to_qm_n(uint64_t user_input,
> +   uint32_t m, uint32_t n)
> +{
> + u64 mag = (user_input & ~BIT_ULL(63)) >> (32 - n);
This doesn't account for n > 32, which is perfectly possible (e.g. Q1.63).
> + bool negative = !!(user_input & BIT_ULL(63));
> + s64 val;
> +
> + /* the range of signed 2s complement is [-2^n+m, 2^n+m - 1] */
> + val = clamp_val(mag, 0, negative ? BIT(n + m) : BIT(n + m) - 1);
This also doesn't account for n + m == 64.
> +
> + return negative ? 0ll - val : val;
> +}
> +EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n);
> +
>  /**
>   * drm_crtc_enable_color_mgmt - enable color management properties
>   * @crtc: DRM CRTC
> diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
> index d1c662d92ab7..60fea5501886 100644
> --- a/include/drm/drm_color_mgmt.h
> +++ b/include/drm/drm_color_mgmt.h
> @@ -30,6 +30,8 @@ struct drm_crtc;
>  struct drm_plane;
> 
>  uint32_t drm_color_lut_extract(uint32_t user_input, uint32_t bit_precision);
> +uint64_t drm_color_ctm_s31_32_to_qm_n(uint64_t user_input,
> +   uint32_t m, uint32_t n);
> 
>  void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
>   uint degamma_lut_size,
> --
> 2.20.1
> 


-- 
Mihail





Re: [PATCH] drm/komeda: Reordered the komeda's de-init functions

2019-08-23 Thread Mihail Atanassov
On Tuesday, 20 August 2019 18:46:19 BST Ayan Halder wrote:
> The de-init routine should be doing the following in order:-
> 1. Unregister the drm device
> 2. Shut down the crtcs - failing to do this might cause a connector leakage
> See the 'commit 109c4d18e574 ("drm/arm/malidp: Ensure that the crtcs are
> shutdown before removing any encoder/connector")'
> 3. Disable the interrupts
> 4. Unbind the components
> 5. Free up DRM mode_config info
> 
> Signed-off-by: Ayan Kumar Halder 
> ---
>  .../gpu/drm/arm/display/komeda/komeda_kms.c   | 20 +--
>  1 file changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c 
> b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> index 89191a555c84..e219d1b67100 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -13,6 +13,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
Can we keep the include list in alphabetical order?
>  #include 
>  #include 
>  
> @@ -304,24 +305,30 @@ struct komeda_kms_dev *komeda_kms_attach(struct 
> komeda_dev *mdev)
>  komeda_kms_irq_handler, IRQF_SHARED,
>  drm->driver->name, drm);
>   if (err)
> - goto cleanup_mode_config;
> + goto free_component_binding;
>  
>   err = mdev->funcs->enable_irq(mdev);
>   if (err)
> - goto cleanup_mode_config;
> + goto free_component_binding;
>  
>   drm->irq_enabled = true;
>  
>   err = drm_dev_register(drm, 0);
>   if (err)
> - goto cleanup_mode_config;
> + goto free_interrupts;
>  
>   return kms;
>  
> -cleanup_mode_config:
> +free_interrupts:
>   drm->irq_enabled = false;
> + mdev->funcs->disable_irq(mdev);
> +free_component_binding:
> + component_unbind_all(mdev->dev, drm);
> +cleanup_mode_config:
>   drm_mode_config_cleanup(drm);
>   komeda_kms_cleanup_private_objs(kms);
> + drm->dev_private = NULL;
> + drm_dev_put(drm);
>  free_kms:
>   kfree(kms);
>   return ERR_PTR(err);
> @@ -332,12 +339,13 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
>   struct drm_device *drm = &kms->base;
>   struct komeda_dev *mdev = drm->dev_private;
>  
> + drm_dev_unregister(drm);
> + drm_atomic_helper_shutdown(drm);
>   drm->irq_enabled = false;
>   mdev->funcs->disable_irq(mdev);
> - drm_dev_unregister(drm);
>   component_unbind_all(mdev->dev, drm);
> - komeda_kms_cleanup_private_objs(kms);
>   drm_mode_config_cleanup(drm);
> + komeda_kms_cleanup_private_objs(kms);
>   drm->dev_private = NULL;
>   drm_dev_put(drm);
>  }
> 

Thanks. See my include order comment above, with that fixed:

Reviewed-by: Mihail Atanassov 

-- 
Mihail





[PATCH] drm/komeda: Add missing of_node_get() call

2019-08-20 Thread Mihail Atanassov
komeda_pipeline_destroy has the matching of_node_put().

Fixes: 29e56aec911dd ("drm/komeda: Add DT parsing")
Signed-off-by: Mihail Atanassov 
---
 drivers/gpu/drm/arm/display/komeda/komeda_dev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c 
b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
index 0142ee991957..ca64a129c594 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
@@ -130,7 +130,7 @@ static int komeda_parse_pipe_dt(struct komeda_dev *mdev, 
struct device_node *np)
of_graph_get_port_by_id(np, KOMEDA_OF_PORT_OUTPUT);
 
pipe->dual_link = pipe->of_output_links[0] && pipe->of_output_links[1];
-   pipe->of_node = np;
+   pipe->of_node = of_node_get(np);
 
return 0;
 }
-- 
2.22.0



Re: [PATCH] drm/komeda: Adds error event print functionality

2019-08-02 Thread Mihail Atanassov
On Friday, 2 August 2019 10:43:10 BST Lowry Li (Arm Technology China) wrote:
> From: "Lowry Li (Arm Technology China)" 
> 
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Changes since v2:
> 1. Refine komeda_sprintf();
> 2. Not using STR_SZ macro for the string size in komeda_print_events().
> 
> Changes since v1:
> 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> 2. Changing the max string size to 256.
> 
> Signed-off-by: Lowry Li (Arm Technology China) 

Reviewed-by: Mihail Atanassov 

BR,
Mihail

> ---
>  drivers/gpu/drm/arm/display/Kconfig   |   6 +
>  drivers/gpu/drm/arm/display/komeda/Makefile   |   2 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140
> ++ drivers/gpu/drm/arm/display/komeda/komeda_kms.c   | 
>  4 +
>  5 files changed, 167 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/Kconfig
> b/drivers/gpu/drm/arm/display/Kconfig index cec0639..e87ff86 100644
> --- a/drivers/gpu/drm/arm/display/Kconfig
> +++ b/drivers/gpu/drm/arm/display/Kconfig
> @@ -12,3 +12,9 @@ config DRM_KOMEDA
> Processor driver. It supports the D71 variants of the hardware.
> 
> If compiled as a module it will be called komeda.
> +
> +config DRM_KOMEDA_ERROR_PRINT
> + bool "Enable komeda error print"
> + depends on DRM_KOMEDA
> + help
> +   Choose this option to enable error printing.
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile
> b/drivers/gpu/drm/arm/display/komeda/Makefile index 5c3900c..f095a1c 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -22,4 +22,6 @@ komeda-y += \
>   d71/d71_dev.o \
>   d71/d71_component.o
> 
> +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> +
>  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index d1c86b6..e28e7e6
> 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG  BIT_ULL(30)
>  #define KOMEDA_ERR_TTF   BIT_ULL(31)
> 
> +#define KOMEDA_ERR_EVENTS\
> + (KOMEDA_EVENT_URUN  | KOMEDA_EVENT_IBSY | KOMEDA_EVENT_OVR |
\
> + KOMEDA_ERR_TETO | KOMEDA_ERR_TEMR   | 
KOMEDA_ERR_TITR |\
> + KOMEDA_ERR_CPE  | KOMEDA_ERR_CFGE   | 
KOMEDA_ERR_AXIE |\
> + KOMEDA_ERR_ACE0 | KOMEDA_ERR_ACE1   | 
KOMEDA_ERR_ACE2 |\
> + KOMEDA_ERR_ACE3 | KOMEDA_ERR_DRIFTTO| 
KOMEDA_ERR_FRAMETO |\
> + KOMEDA_ERR_ZME  | KOMEDA_ERR_MERR   | 
KOMEDA_ERR_TCF |\
> + KOMEDA_ERR_TTNG | KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS   KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>   MALI_D71 = 0,
> @@ -207,4 +218,8 @@ struct komeda_dev {
> 
>  struct komeda_dev *dev_to_mdev(struct device *dev);
> 
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +void komeda_print_events(struct komeda_events *evts);
> +#endif
> +
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> b/drivers/gpu/drm/arm/display/komeda/komeda_event.c new file mode 100644
> index 000..a36fb86
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,140 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang 
> + *
> + */
> +#include 
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> + char *str;
> + u32 sz;
> + u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> + va_list args;
> + int num, free_sz;
> + int err;
> +
> + free_sz = str->sz - str->len - 1;
> + if (free_sz <= 0)
> + return -ENOSPC;
> +
> + va_start(args, fmt);
> +
> + num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> + va_end(args);
> +
> + if (num < free_sz) {
> + str->len += num;
> + err = 0;
> + } else {
> + str->len = str->sz - 1;
> + err = -ENOSPC;
> + }
> +
> + return err;
> +}
&

[PATCH] drm: mali-dp: add atomic_print_state for planes

2017-02-13 Thread Mihail Atanassov
Print all the extra fields of malidp_plane_state.

Signed-off-by: Mihail Atanassov 
---
 drivers/gpu/drm/arm/malidp_planes.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/arm/malidp_planes.c 
b/drivers/gpu/drm/arm/malidp_planes.c
index 414aada..3879dc5 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "malidp_hw.h"
 #include "malidp_drv.h"
@@ -88,6 +89,17 @@ static void malidp_destroy_plane_state(struct drm_plane 
*plane,
kfree(m_state);
 }
 
+static void malidp_plane_atomic_print_state(struct drm_printer *p,
+   const struct drm_plane_state *state)
+{
+   struct malidp_plane_state *ms = to_malidp_plane_state(state);
+   struct malidp_plane *mp = to_malidp_plane(state->plane);
+
+   drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size);
+   drm_printf(p, "\tformat_id=%u\n", ms->format);
+   drm_printf(p, "\tn_planes=%u\n", ms->n_planes);
+}
+
 static const struct drm_plane_funcs malidp_de_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
@@ -96,6 +108,7 @@ static void malidp_destroy_plane_state(struct drm_plane 
*plane,
.reset = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = malidp_duplicate_plane_state,
.atomic_destroy_state = malidp_destroy_plane_state,
+   .atomic_print_state = malidp_plane_atomic_print_state,
 };
 
 static int malidp_de_plane_check(struct drm_plane *plane,
-- 
1.9.1



[PATCH v2] drm: mali-dp: Add CTM support

2017-02-13 Thread Mihail Atanassov
All DPs have a COLORADJ matrix which is applied prior to output gamma.
Attach that to the CTM property. Also, ensure the input CTM's coefficients
can fit in the DP registers' Q3.12 format.

Signed-off-by: Mihail Atanassov 
---

Link to v1: https://lkml.org/lkml/2017/2/1/254

Changes since v1:
 - Rebased and fixed conflicts
 - Improved clarity of overflow check (+comment)
 - Moved call to malidp_atomic_commit_update_coloradj in the existing crtc
 for-each loop

This patch depends on "[PATCH v3 2/2] drm: mali-dp: enable gamma support", sent
out on 7 Feb (https://lkml.org/lkml/2017/2/7/547).

 drivers/gpu/drm/arm/malidp_crtc.c | 58 +--
 drivers/gpu/drm/arm/malidp_drv.c  | 36 +++-
 drivers/gpu/drm/arm/malidp_drv.h  |  1 +
 drivers/gpu/drm/arm/malidp_regs.h |  2 ++
 4 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index 6a46520..7414540 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -192,6 +192,58 @@ static int malidp_crtc_atomic_check_gamma(struct drm_crtc 
*crtc,
return 0;
 }
 
+/*
+ * Check if there is a new CTM and if it contains valid input. Valid here means
+ * that the number is inside the representable range for a Q3.12 number,
+ * excluding truncating the fractional part of the input data.
+ *
+ * The COLORADJ registers can be changed atomically.
+ */
+static int malidp_crtc_atomic_check_ctm(struct drm_crtc *crtc,
+   struct drm_crtc_state *state)
+{
+   struct malidp_crtc_state *mc = to_malidp_crtc_state(state);
+   struct drm_color_ctm *ctm;
+   int i;
+
+   if (!state->color_mgmt_changed)
+   return 0;
+
+   if (!state->ctm)
+   return 0;
+
+   if (crtc->state->ctm && (crtc->state->ctm->base.id ==
+state->ctm->base.id))
+   return 0;
+
+   /*
+* The size of the ctm is checked in
+* drm_atomic_replace_property_blob_from_id.
+*/
+   ctm = (struct drm_color_ctm *)state->ctm->data;
+   for (i = 0; i < ARRAY_SIZE(ctm->matrix); ++i) {
+   /* Convert from S31.32 to Q3.12. */
+   s64 val = ctm->matrix[i];
+   u32 mag = u64)val) & ~BIT_ULL(63)) >> 20) &
+ GENMASK_ULL(14, 0);
+
+   /*
+* Convert to 2s complement and check the destination's top bit
+* for overflow. NB: Can't check before converting or it'd
+* incorrectly reject the case:
+* sign == 1
+* mag == 0x2000
+*/
+   if (val & BIT_ULL(63))
+   mag = ~mag + 1;
+   if (!!(val & BIT_ULL(63)) != !!(mag & BIT(14)))
+   return -EINVAL;
+   mc->coloradj_coeffs[i] = mag;
+   }
+
+   return 0;
+}
+
 static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_crtc_state *state)
 {
@@ -269,6 +321,7 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
}
 
ret = malidp_crtc_atomic_check_gamma(crtc, state);
+   ret = ret ? ret : malidp_crtc_atomic_check_ctm(crtc, state);
 
return ret;
 }
@@ -288,6 +341,7 @@ static struct drm_crtc_state 
*malidp_crtc_duplicate_state(struct drm_crtc *crtc)
 
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
memcpy(state->gamma_coeffs, cs->gamma_coeffs, 
sizeof(state->gamma_coeffs));
+   memcpy(state->coloradj_coeffs, cs->coloradj_coeffs, 
sizeof(state->coloradj_coeffs));
 
return &state->base;
 }
@@ -358,8 +412,8 @@ int malidp_crtc_init(struct drm_device *drm)
 
drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs);
drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE);
-   /* No inverse-gamma and color adjustments yet. */
-   drm_crtc_enable_color_mgmt(&malidp->crtc, 0, false, 
MALIDP_GAMMA_LUT_SIZE);
+   /* No inverse-gamma: it is per-plane. */
+   drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, 
MALIDP_GAMMA_LUT_SIZE);
return 0;
 
 crtc_cleanup_planes:
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index ce741c3..15f0f91 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -77,6 +77,37 @@ static void malidp_atomic_commit_update_gamma(struct 
drm_crtc *crtc,
}
 }
 
+static
+void malidp_atomic_commit_update_coloradj(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+   struct malidp_drm *malidp = crtc_to_malidp_device(c

[RFC] drm: Helper macro for drm state duplication

2017-02-09 Thread Mihail Atanassov
Hi,

I was working on a few patches adding fields to struct malidp_crtc_state and
found myself writing memcpy multiple times in the ->atomic_duplicate_state
hook because I wanted to avoid copying the drm_crtc_state twice
(__drm_atomic_helper_crtc_duplicate_state copies it already). I figured this
also applies to the other drm_*_state derivatives, so I concocted a macro
helper to do the copy in one chunk (two if you count the __drm_atomic_helper*
one). I'd appreciate some comments on whether anyone else might find this
macro useful. Thanks!

Mihail Atanassov (1):
  drm: Add helper macro for duplicating custom drm_*_state

 include/drm/drm_atomic_helper.h | 33 +
 1 file changed, 33 insertions(+)

-- 
Mihail Atanassov



[PATCH] drm: Add helper macro for duplicating custom drm_*_state

2017-02-09 Thread Mihail Atanassov
Assuming a derived struct of the form:

struct foo_bar_state
{
struct drm_bar_state bar_state;
struct foo_private priv;
struct foo_private2 *priv2;
};

memcpy priv and priv2 to the new instance of foo_bar_state. The
intention is to use this macro in ->atomic_duplicate_state in conjunction with
__drm_atomic_helper_*_duplicate_state, which already copies the relevant
drm_*_state struct.

There's an equality check for new_state and old_state to ensure that
they are distinct instances of the same type, and a BUILD_BUG if the
base struct (bar_state in the above example) is not first in the derived
struct, to avoid missing any data before it and corrupting the base's data.

Signed-off-by: Mihail Atanassov 
---
 include/drm/drm_atomic_helper.h | 33 +
 1 file changed, 33 insertions(+)

diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index d066e94..ecc6a82 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -171,6 +171,39 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc 
*crtc,
   uint32_t size);
 
 /**
+ * drm_atomic_duplicate_custom_state - helper macro for duplicating
+ * driver-private additions to drm_*_state.
+ * @new_state: pointer to destination state struct
+ * @old_state: pointer to source state struct
+ * @basename: name of the drm_*_state member of the new_state/old_state struct
+ *
+ * Copies the data after the base struct until the end of the custom struct,
+ * e.g. given a structure
+ *
+ * struct foo_bar_state {
+ * struct drm_bar_state base;
+ * struct foo_private priv;
+ * struct foo_private2 *priv2;
+ * };
+ *
+ * this copies priv and priv2. NB: the base struct *must* be the first element
+ * of the derived struct, and new_state and old_state have to be two distinct
+ * instances.
+ */
+#define drm_atomic_helper_duplicate_custom_state(new_state, old_state, 
basename) \
+   do { \
+   size_t base_size = sizeof(new_state->basename); \
+   size_t base_offset = offsetof(typeof(*new_state), basename); \
+   \
+   BUILD_BUG_ON(base_offset != 0); \
+   if (new_state == old_state) /* Type-check */ \
+   break; \
+   memcpy((char *)new_state + base_size, \
+  (char *)old_state + base_size, \
+  sizeof(*new_state) - base_size); \
+   } while(0)
+
+/**
  * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to 
CRTC
  * @plane: the loop cursor
  * @crtc:  the crtc whose planes are iterated
-- 
1.9.1



[PATCH v3 1/2] drm: mali-dp: add malidp_crtc_state struct

2017-02-07 Thread Mihail Atanassov
Add a custom CRTC state struct to enable storing driver-private per-CRTC
state. This patch only adds the base drm_crtc_state struct.

Signed-off-by: Mihail Atanassov 
Reviewed-by: Brian Starkey 
Acked-by: Liviu Dudau 
---
Link to v2: https://lkml.org/lkml/2017/2/1/378
Link to v1: https://lkml.org/lkml/2017/2/1/203

Changes since v2:
 - rebased and fixed conflicts
 - s/MALIDP_DISP_FUNC_GAM/MALIDP_DISP_FUNC_GAMMA/g
 - added MALIDP_GAMMA_LUT_SIZE #define + s/4096/MALIDP_GAMMA_LUT_SIZE/g in
 malidp_crtc.c
 - improved readability in a few places

Changes since v1:
 - Moved unused variable to patch 2/2, where it is used.

 drivers/gpu/drm/arm/malidp_crtc.c | 37 +++--
 drivers/gpu/drm/arm/malidp_drv.h  |  6 ++
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index 08e6a71..ebf57e6 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -160,6 +160,39 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
return 0;
 }
 
+static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc 
*crtc)
+{
+   struct malidp_crtc_state *state;
+
+   if (WARN_ON(!crtc->state))
+   return NULL;
+
+   state = kmalloc(sizeof(*state), GFP_KERNEL);
+   if (!state)
+   return NULL;
+
+   __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
+
+   return &state->base;
+}
+
+static void malidp_crtc_reset(struct drm_crtc *crtc)
+{
+   struct malidp_crtc_state *cs = (crtc->state) ?
+  to_malidp_crtc_state(crtc->state) : NULL;
+
+   if (crtc->state)
+   __drm_atomic_helper_crtc_destroy_state(crtc->state);
+
+   kfree(cs);
+   cs = kzalloc(sizeof(*cs), GFP_KERNEL);
+   if (!cs)
+   return;
+
+   crtc->state = &cs->base;
+   crtc->state->crtc = crtc;
+}
+
 static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = {
.mode_fixup = malidp_crtc_mode_fixup,
.enable = malidp_crtc_enable,
@@ -171,8 +204,8 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
-   .reset = drm_atomic_helper_crtc_reset,
-   .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+   .reset = malidp_crtc_reset,
+   .atomic_duplicate_state = malidp_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index dbc617c..558f4bf 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -47,6 +47,12 @@ struct malidp_plane_state {
 #define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
 #define to_malidp_plane_state(x) container_of(x, struct malidp_plane_state, 
base)
 
+struct malidp_crtc_state {
+   struct drm_crtc_state base;
+};
+
+#define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base)
+
 int malidp_de_planes_init(struct drm_device *drm);
 void malidp_de_planes_destroy(struct drm_device *drm);
 int malidp_crtc_init(struct drm_device *drm);
-- 
1.9.1



[PATCH v3 2/2] drm: mali-dp: enable gamma support

2017-02-07 Thread Mihail Atanassov
Add gamma via the DRM GAMMA_LUT/GAMMA_LUT_SIZE CRTC
properties. The expected LUT size is 4096 in order
to produce as accurate a set of segments as possible.

This version uses only the green channel's gamma curve
to set the hardware curve on DP550/650. For the sake of
simplicity, it uses the same table of coefficients for
all 3 curves on DP500.

Signed-off-by: Mihail Atanassov 
Reviewed-by: Brian Starkey 
Acked-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/malidp_crtc.c | 130 --
 drivers/gpu/drm/arm/malidp_drv.c  |  52 +++
 drivers/gpu/drm/arm/malidp_drv.h  |   1 +
 drivers/gpu/drm/arm/malidp_hw.c   |   3 +
 drivers/gpu/drm/arm/malidp_hw.h   |   2 +
 drivers/gpu/drm/arm/malidp_regs.h |  19 --
 6 files changed, 196 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index ebf57e6..6a46520 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -21,6 +21,8 @@
 #include "malidp_drv.h"
 #include "malidp_hw.h"
 
+#define MALIDP_GAMMA_LUT_SIZE 4096
+
 static bool malidp_crtc_mode_fixup(struct drm_crtc *crtc,
   const struct drm_display_mode *mode,
   struct drm_display_mode *adjusted_mode)
@@ -82,6 +84,114 @@ static void malidp_crtc_disable(struct drm_crtc *crtc)
clk_disable_unprepare(hwdev->pxlclk);
 }
 
+static const struct gamma_curve_segment {
+   u16 start;
+   u16 end;
+} segments[MALIDP_COEFFTAB_NUM_COEFFS] = {
+   /* sector 0 */
+   {0,0 }, {1,1 }, {2,2 }, {3,3 },
+   {4,4 }, {5,5 }, {6,6 }, {7,7 },
+   {8,8 }, {9,9 }, {   10,   10 }, {   11,   11 },
+   {   12,   12 }, {   13,   13 }, {   14,   14 }, {   15,   15 },
+   /* sector 1 */
+   {   16,   19 }, {   20,   23 }, {   24,   27 }, {   28,   31 },
+   /* sector 2 */
+   {   32,   39 }, {   40,   47 }, {   48,   55 }, {   56,   63 },
+   /* sector 3 */
+   {   64,   79 }, {   80,   95 }, {   96,  111 }, {  112,  127 },
+   /* sector 4 */
+   {  128,  159 }, {  160,  191 }, {  192,  223 }, {  224,  255 },
+   /* sector 5 */
+   {  256,  319 }, {  320,  383 }, {  384,  447 }, {  448,  511 },
+   /* sector 6 */
+   {  512,  639 }, {  640,  767 }, {  768,  895 }, {  896, 1023 },
+   { 1024, 1151 }, { 1152, 1279 }, { 1280, 1407 }, { 1408, 1535 },
+   { 1536, 1663 }, { 1664, 1791 }, { 1792, 1919 }, { 1920, 2047 },
+   { 2048, 2175 }, { 2176, 2303 }, { 2304, 2431 }, { 2432, 2559 },
+   { 2560, 2687 }, { 2688, 2815 }, { 2816, 2943 }, { 2944, 3071 },
+   { 3072, 3199 }, { 3200, 3327 }, { 3328, 3455 }, { 3456, 3583 },
+   { 3584, 3711 }, { 3712, 3839 }, { 3840, 3967 }, { 3968, 4095 },
+};
+
+#define DE_COEFTAB_DATA(a, b) a) & 0xfff) << 16) | (((b) & 0xfff)))
+
+static void malidp_generate_gamma_table(struct drm_property_blob *lut_blob,
+   u32 coeffs[MALIDP_COEFFTAB_NUM_COEFFS])
+{
+   struct drm_color_lut *lut = (struct drm_color_lut *)lut_blob->data;
+   int i;
+
+   for (i = 0; i < MALIDP_COEFFTAB_NUM_COEFFS; ++i) {
+   u32 a, b;
+   u32 delta_in;
+   u32 out_start, out_end;
+
+   delta_in = segments[i].end - segments[i].start;
+   /* DP has 12-bit internal precision for its LUTs. */
+   out_start = drm_color_lut_extract(lut[segments[i].start].green,
+ 12);
+   out_end = drm_color_lut_extract(lut[segments[i].end].green, 12);
+   a = (delta_in == 0) ?
+   0 : ((out_end - out_start) * 256) / delta_in;
+   b = out_start;
+   coeffs[i] = DE_COEFTAB_DATA(a, b);
+   }
+}
+
+/*
+ * Check if there is a new gamma LUT and if it is of an acceptable size. Also,
+ * reject any LUTs that use distinct red, green, and blue curves.
+ */
+static int malidp_crtc_atomic_check_gamma(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+   struct malidp_crtc_state *mc = to_malidp_crtc_state(state);
+   struct drm_color_lut *lut;
+   size_t lut_size;
+   int i;
+
+   if (!state->color_mgmt_changed)
+   return 0;
+
+   if (!state->gamma_lut)
+   return 0;
+
+   if (crtc->state->gamma_lut && (crtc->state->gamma_lut->base.id ==
+  state->gamma_lut->base.id))
+   return 0;
+
+   if (state->gamma_lut->length % sizeof(struct drm_color_lut))
+   return -EINVAL;
+
+   lut_size = state->gamma_lut->length / sizeof(struct drm_color_lut);
+   if (lut_size != MALIDP_GAMMA_LUT_SIZE)
+   return

[PATCH v2 1/2] drm: mali-dp: add malidp_crtc_state struct

2017-02-01 Thread Mihail Atanassov
Add a custom CRTC state struct to enable storing driver-private per-CRTC
state. This patch only adds the base drm_crtc_state struct.

Signed-off-by: Mihail Atanassov 
Reviewed-by: Brian Starkey 
---
Link to v1: https://lkml.org/lkml/2017/2/1/203
Changes since v1:
 - Moved unused variable to patch 2/2, where it is used.

 drivers/gpu/drm/arm/malidp_crtc.c | 37 +++--
 drivers/gpu/drm/arm/malidp_drv.h  |  6 ++
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index 08e6a71..ebf57e6 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -160,6 +160,39 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
return 0;
 }
 
+static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc 
*crtc)
+{
+   struct malidp_crtc_state *state;
+
+   if (WARN_ON(!crtc->state))
+   return NULL;
+
+   state = kmalloc(sizeof(*state), GFP_KERNEL);
+   if (!state)
+   return NULL;
+
+   __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
+
+   return &state->base;
+}
+
+static void malidp_crtc_reset(struct drm_crtc *crtc)
+{
+   struct malidp_crtc_state *cs = (crtc->state) ?
+  to_malidp_crtc_state(crtc->state) : NULL;
+
+   if (crtc->state)
+   __drm_atomic_helper_crtc_destroy_state(crtc->state);
+
+   kfree(cs);
+   cs = kzalloc(sizeof(*cs), GFP_KERNEL);
+   if (!cs)
+   return;
+
+   crtc->state = &cs->base;
+   crtc->state->crtc = crtc;
+}
+
 static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = {
.mode_fixup = malidp_crtc_mode_fixup,
.enable = malidp_crtc_enable,
@@ -171,8 +204,8 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
-   .reset = drm_atomic_helper_crtc_reset,
-   .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+   .reset = malidp_crtc_reset,
+   .atomic_duplicate_state = malidp_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index 9fc8a2e..c7a69ae 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -47,6 +47,12 @@ struct malidp_plane_state {
 #define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
 #define to_malidp_plane_state(x) container_of(x, struct malidp_plane_state, 
base)
 
+struct malidp_crtc_state {
+   struct drm_crtc_state base;
+};
+
+#define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base)
+
 int malidp_de_planes_init(struct drm_device *drm);
 void malidp_de_planes_destroy(struct drm_device *drm);
 int malidp_crtc_init(struct drm_device *drm);
-- 
1.9.1



[PATCH v2 2/2] drm: mali-dp: enable gamma support

2017-02-01 Thread Mihail Atanassov
Add gamma via the DRM GAMMA_LUT/GAMMA_LUT_SIZE CRTC
properties. The expected LUT size is 4096 in order
to produce as accurate a set of segments as possible.

This version uses only the green channel's gamma curve
to set the hardware curve on DP550/650. For the sake of
simplicity, it uses the same table of coefficients for
all 3 curves on DP500.

Signed-off-by: Mihail Atanassov 
Reviewed-by: Brian Starkey 
---
 drivers/gpu/drm/arm/malidp_crtc.c | 132 --
 drivers/gpu/drm/arm/malidp_drv.c  |  52 +++
 drivers/gpu/drm/arm/malidp_drv.h  |   1 +
 drivers/gpu/drm/arm/malidp_hw.c   |   3 +
 drivers/gpu/drm/arm/malidp_hw.h   |   2 +
 drivers/gpu/drm/arm/malidp_regs.h |  19 --
 6 files changed, 199 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index ebf57e6..10f79b6 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -82,6 +82,114 @@ static void malidp_crtc_disable(struct drm_crtc *crtc)
clk_disable_unprepare(hwdev->pxlclk);
 }
 
+static const struct gamma_curve_segment {
+   u16 start;
+   u16 end;
+} segments[MALIDP_COEFFTAB_NUM_COEFFS] = {
+   /* sector 0 */
+   {0,0 }, {1,1 }, {2,2 }, {3,3 },
+   {4,4 }, {5,5 }, {6,6 }, {7,7 },
+   {8,8 }, {9,9 }, {   10,   10 }, {   11,   11 },
+   {   12,   12 }, {   13,   13 }, {   14,   14 }, {   15,   15 },
+   /* sector 1 */
+   {   16,   19 }, {   20,   23 }, {   24,   27 }, {   28,   31 },
+   /* sector 2 */
+   {   32,   39 }, {   40,   47 }, {   48,   55 }, {   56,   63 },
+   /* sector 3 */
+   {   64,   79 }, {   80,   95 }, {   96,  111 }, {  112,  127 },
+   /* sector 4 */
+   {  128,  159 }, {  160,  191 }, {  192,  223 }, {  224,  255 },
+   /* sector 5 */
+   {  256,  319 }, {  320,  383 }, {  384,  447 }, {  448,  511 },
+   /* sector 6 */
+   {  512,  639 }, {  640,  767 }, {  768,  895 }, {  896, 1023 },
+   { 1024, 1151 }, { 1152, 1279 }, { 1280, 1407 }, { 1408, 1535 },
+   { 1536, 1663 }, { 1664, 1791 }, { 1792, 1919 }, { 1920, 2047 },
+   { 2048, 2175 }, { 2176, 2303 }, { 2304, 2431 }, { 2432, 2559 },
+   { 2560, 2687 }, { 2688, 2815 }, { 2816, 2943 }, { 2944, 3071 },
+   { 3072, 3199 }, { 3200, 3327 }, { 3328, 3455 }, { 3456, 3583 },
+   { 3584, 3711 }, { 3712, 3839 }, { 3840, 3967 }, { 3968, 4095 },
+};
+
+#define DE_COEFTAB_DATA(a, b) a) & 0xfff) << 16) | (((b) & 0xfff)))
+
+static void malidp_generate_gamma_table(struct drm_property_blob *lut_blob,
+   u32 coeffs[MALIDP_COEFFTAB_NUM_COEFFS])
+{
+   struct drm_color_lut *lut = (struct drm_color_lut *)lut_blob->data;
+   int i;
+
+   for (i = 0; i < MALIDP_COEFFTAB_NUM_COEFFS; ++i) {
+   u32 a, b;
+   u32 delta_in;
+   u32 out_start, out_end;
+
+   delta_in = segments[i].end - segments[i].start;
+   /* DP has 12-bit internal precision for its LUTs. */
+   out_start = drm_color_lut_extract(lut[segments[i].start].green,
+ 12);
+   out_end = drm_color_lut_extract(lut[segments[i].end].green, 12);
+   a = (delta_in == 0) ?
+   0 : ((out_end - out_start) * 256) / delta_in;
+   b = out_start;
+   coeffs[i] = DE_COEFTAB_DATA(a, b);
+   }
+}
+
+/*
+ * Check if there is a new gamma LUT and if it is of an acceptable size. Also,
+ * reject any LUTs that use distinct red, green, and blue curves.
+ */
+static int malidp_crtc_atomic_check_gamma(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+   struct malidp_crtc_state *mc = to_malidp_crtc_state(state);
+   struct drm_color_lut *lut;
+   size_t lut_size;
+   int i;
+
+   if (!state->color_mgmt_changed)
+   return 0;
+
+   if (!state->gamma_lut)
+   return 0;
+
+   if (crtc->state->gamma_lut && (crtc->state->gamma_lut->base.id ==
+  state->gamma_lut->base.id))
+   return 0;
+
+   if (state->gamma_lut->length % sizeof(struct drm_color_lut))
+   return -EINVAL;
+
+   lut_size = state->gamma_lut->length / sizeof(struct drm_color_lut);
+   if (lut_size != 4096)
+   return -EINVAL;
+
+   lut = (struct drm_color_lut *)state->gamma_lut->data;
+   for (i = 0; i < lut_size; ++i)
+   if (!((lut[i].red == lut[i].green) &&
+ (lut[i].red == lut[i].blue)))
+   return -EINVAL;
+
+   if (!state->mode_changed) {
+   int ret;
+
+   state->mode_c

[PATCH] drm: mali-dp: Add CTM support

2017-02-01 Thread Mihail Atanassov
All DPs have a COLORADJ matrix which is applied prior to output gamma.
Attach that to the CTM property. Also, ensure the input CTM's coefficients
can fit in the DP registers' Q3.12 format.

Signed-off-by: Mihail Atanassov 
---

This patch depends on "[PATCH 2/2] drm: mali-dp: enable gamma support", sent
out earlier (https://lkml.org/lkml/2017/2/1/201).

 drivers/gpu/drm/arm/malidp_crtc.c | 59 +--
 drivers/gpu/drm/arm/malidp_drv.c  | 35 +++
 drivers/gpu/drm/arm/malidp_drv.h  |  1 +
 drivers/gpu/drm/arm/malidp_regs.h |  2 ++
 4 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index 10f79b6..2f366e4 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -190,6 +190,55 @@ static int malidp_crtc_atomic_check_gamma(struct drm_crtc 
*crtc,
return 0;
 }
 
+/*
+ * Check if there is a new CTM and if it contains valid input. Valid here means
+ * that the number is inside the representable range for a Q3.12 number,
+ * excluding truncating the fractional part of the input data.
+ *
+ * The COLORADJ registers can be changed atomically.
+ */
+static int malidp_crtc_atomic_check_ctm(struct drm_crtc *crtc,
+   struct drm_crtc_state *state)
+{
+   struct malidp_crtc_state *mc = to_malidp_crtc_state(state);
+   struct drm_color_ctm *ctm;
+   int i;
+
+   if (!state->color_mgmt_changed)
+   return 0;
+
+   if (!state->ctm)
+   return 0;
+
+   if (crtc->state->ctm && (crtc->state->ctm->base.id ==
+state->ctm->base.id))
+   return 0;
+
+   /*
+* The size of the ctm is checked in
+* drm_atomic_replace_property_blob_from_id.
+*/
+   ctm = (struct drm_color_ctm *)state->ctm->data;
+   for (i = 0; i < ARRAY_SIZE(ctm->matrix); ++i) {
+   /* Convert from S31.32 to Q3.12. */
+   s64 val = ctm->matrix[i];
+   u64 mag = u64)val) & ~BIT_ULL(63)) >> 20) &
+ GENMASK_ULL(14, 0);
+
+   /* Check the destination's top bit for overflow. */
+   if (val & BIT_ULL(63)) {
+   mag = ~mag + 1;
+   if (!(mag & BIT_ULL(14)))
+   return -EINVAL;
+   } else if (mag & BIT_ULL(14)) {
+   return -EINVAL;
+   }
+   mc->coloradj_coeffs[i] = mag;
+   }
+
+   return 0;
+}
+
 static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_crtc_state *state)
 {
@@ -270,6 +319,10 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
if (ret)
return ret;
 
+   ret = malidp_crtc_atomic_check_ctm(crtc, state);
+   if (ret)
+   return ret;
+
return 0;
 }
 
@@ -289,6 +342,8 @@ static struct drm_crtc_state 
*malidp_crtc_duplicate_state(struct drm_crtc *crtc)
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
memcpy(state->gamma_coeffs, cs->gamma_coeffs,
   sizeof(state->gamma_coeffs));
+   memcpy(state->coloradj_coeffs, cs->coloradj_coeffs,
+  sizeof(state->coloradj_coeffs));
 
return &state->base;
 }
@@ -359,10 +414,10 @@ int malidp_crtc_init(struct drm_device *drm)
 
drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs);
drm_mode_crtc_set_gamma_size(&malidp->crtc, 4096);
-   /* No inverse-gamma and color adjustments yet. */
+   /* No inverse-gamma: it is per-plane. */
drm_crtc_enable_color_mgmt(&malidp->crtc,
   0,
-  false,
+  true,
   4096);
return 0;
 
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index a9f787d..682901a 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -78,6 +78,37 @@ static void malidp_atomic_commit_update_gamma(struct 
drm_crtc *crtc,
}
 }
 
+static
+void malidp_atomic_commit_update_coloradj(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+   struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
+   struct malidp_hw_device *hwdev = malidp->dev;
+   int i;
+
+   if (!crtc->state->color_mgmt_changed)
+   return;
+
+   if (!crtc->state->ctm) {
+   malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_CADJ,
+   MALIDP_DE_DISPLAY_FUNC);
+   } else

[PATCH 1/2] drm: mali-dp: add malidp_crtc_state struct

2017-02-01 Thread Mihail Atanassov
Add a custom CRTC state struct to enable storing driver-private per-CRTC
state. This patch only adds the base drm_crtc_state struct.

Signed-off-by: Mihail Atanassov 
---
 drivers/gpu/drm/arm/malidp_crtc.c | 39 +--
 drivers/gpu/drm/arm/malidp_drv.h  |  6 ++
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index 08e6a71..d1cd0e7 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -160,6 +160,41 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
return 0;
 }
 
+static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc 
*crtc)
+{
+   struct malidp_crtc_state *cs;
+   struct malidp_crtc_state *state;
+
+   if (WARN_ON(!crtc->state))
+   return NULL;
+
+   cs = to_malidp_crtc_state(crtc->state);
+   state = kmalloc(sizeof(*state), GFP_KERNEL);
+   if (!state)
+   return NULL;
+
+   __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
+
+   return &state->base;
+}
+
+static void malidp_crtc_reset(struct drm_crtc *crtc)
+{
+   struct malidp_crtc_state *cs = (crtc->state) ?
+  to_malidp_crtc_state(crtc->state) : NULL;
+
+   if (crtc->state)
+   __drm_atomic_helper_crtc_destroy_state(crtc->state);
+
+   kfree(cs);
+   cs = kzalloc(sizeof(*cs), GFP_KERNEL);
+   if (!cs)
+   return;
+
+   crtc->state = &cs->base;
+   crtc->state->crtc = crtc;
+}
+
 static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = {
.mode_fixup = malidp_crtc_mode_fixup,
.enable = malidp_crtc_enable,
@@ -171,8 +206,8 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
-   .reset = drm_atomic_helper_crtc_reset,
-   .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+   .reset = malidp_crtc_reset,
+   .atomic_duplicate_state = malidp_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index 9fc8a2e..c7a69ae 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -47,6 +47,12 @@ struct malidp_plane_state {
 #define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
 #define to_malidp_plane_state(x) container_of(x, struct malidp_plane_state, 
base)
 
+struct malidp_crtc_state {
+   struct drm_crtc_state base;
+};
+
+#define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base)
+
 int malidp_de_planes_init(struct drm_device *drm);
 void malidp_de_planes_destroy(struct drm_device *drm);
 int malidp_crtc_init(struct drm_device *drm);
-- 
1.9.1



[PATCH 2/2] drm: mali-dp: enable gamma support

2017-02-01 Thread Mihail Atanassov
Add gamma via the DRM GAMMA_LUT/GAMMA_LUT_SIZE CRTC
properties. The expected LUT size is 4096 in order
to produce as accurate a set of segments as possible.

This version uses only the green channel's gamma curve
to set the hardware curve on DP550/650. For the sake of
simplicity, it uses the same table of coefficients for
all 3 curves on DP500.

Signed-off-by: Mihail Atanassov 
---
 drivers/gpu/drm/arm/malidp_crtc.c | 130 --
 drivers/gpu/drm/arm/malidp_drv.c  |  52 +++
 drivers/gpu/drm/arm/malidp_drv.h  |   1 +
 drivers/gpu/drm/arm/malidp_hw.c   |   3 +
 drivers/gpu/drm/arm/malidp_hw.h   |   2 +
 drivers/gpu/drm/arm/malidp_regs.h |  19 --
 6 files changed, 197 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index d1cd0e7..10f79b6 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -82,6 +82,114 @@ static void malidp_crtc_disable(struct drm_crtc *crtc)
clk_disable_unprepare(hwdev->pxlclk);
 }
 
+static const struct gamma_curve_segment {
+   u16 start;
+   u16 end;
+} segments[MALIDP_COEFFTAB_NUM_COEFFS] = {
+   /* sector 0 */
+   {0,0 }, {1,1 }, {2,2 }, {3,3 },
+   {4,4 }, {5,5 }, {6,6 }, {7,7 },
+   {8,8 }, {9,9 }, {   10,   10 }, {   11,   11 },
+   {   12,   12 }, {   13,   13 }, {   14,   14 }, {   15,   15 },
+   /* sector 1 */
+   {   16,   19 }, {   20,   23 }, {   24,   27 }, {   28,   31 },
+   /* sector 2 */
+   {   32,   39 }, {   40,   47 }, {   48,   55 }, {   56,   63 },
+   /* sector 3 */
+   {   64,   79 }, {   80,   95 }, {   96,  111 }, {  112,  127 },
+   /* sector 4 */
+   {  128,  159 }, {  160,  191 }, {  192,  223 }, {  224,  255 },
+   /* sector 5 */
+   {  256,  319 }, {  320,  383 }, {  384,  447 }, {  448,  511 },
+   /* sector 6 */
+   {  512,  639 }, {  640,  767 }, {  768,  895 }, {  896, 1023 },
+   { 1024, 1151 }, { 1152, 1279 }, { 1280, 1407 }, { 1408, 1535 },
+   { 1536, 1663 }, { 1664, 1791 }, { 1792, 1919 }, { 1920, 2047 },
+   { 2048, 2175 }, { 2176, 2303 }, { 2304, 2431 }, { 2432, 2559 },
+   { 2560, 2687 }, { 2688, 2815 }, { 2816, 2943 }, { 2944, 3071 },
+   { 3072, 3199 }, { 3200, 3327 }, { 3328, 3455 }, { 3456, 3583 },
+   { 3584, 3711 }, { 3712, 3839 }, { 3840, 3967 }, { 3968, 4095 },
+};
+
+#define DE_COEFTAB_DATA(a, b) a) & 0xfff) << 16) | (((b) & 0xfff)))
+
+static void malidp_generate_gamma_table(struct drm_property_blob *lut_blob,
+   u32 coeffs[MALIDP_COEFFTAB_NUM_COEFFS])
+{
+   struct drm_color_lut *lut = (struct drm_color_lut *)lut_blob->data;
+   int i;
+
+   for (i = 0; i < MALIDP_COEFFTAB_NUM_COEFFS; ++i) {
+   u32 a, b;
+   u32 delta_in;
+   u32 out_start, out_end;
+
+   delta_in = segments[i].end - segments[i].start;
+   /* DP has 12-bit internal precision for its LUTs. */
+   out_start = drm_color_lut_extract(lut[segments[i].start].green,
+ 12);
+   out_end = drm_color_lut_extract(lut[segments[i].end].green, 12);
+   a = (delta_in == 0) ?
+   0 : ((out_end - out_start) * 256) / delta_in;
+   b = out_start;
+   coeffs[i] = DE_COEFTAB_DATA(a, b);
+   }
+}
+
+/*
+ * Check if there is a new gamma LUT and if it is of an acceptable size. Also,
+ * reject any LUTs that use distinct red, green, and blue curves.
+ */
+static int malidp_crtc_atomic_check_gamma(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+   struct malidp_crtc_state *mc = to_malidp_crtc_state(state);
+   struct drm_color_lut *lut;
+   size_t lut_size;
+   int i;
+
+   if (!state->color_mgmt_changed)
+   return 0;
+
+   if (!state->gamma_lut)
+   return 0;
+
+   if (crtc->state->gamma_lut && (crtc->state->gamma_lut->base.id ==
+  state->gamma_lut->base.id))
+   return 0;
+
+   if (state->gamma_lut->length % sizeof(struct drm_color_lut))
+   return -EINVAL;
+
+   lut_size = state->gamma_lut->length / sizeof(struct drm_color_lut);
+   if (lut_size != 4096)
+   return -EINVAL;
+
+   lut = (struct drm_color_lut *)state->gamma_lut->data;
+   for (i = 0; i < lut_size; ++i)
+   if (!((lut[i].red == lut[i].green) &&
+ (lut[i].red == lut[i].blue)))
+   return -EINVAL;
+
+   if (!state->mode_changed) {
+   int ret;
+
+   state->mode_changed = true;

[PATCH] drm: mali-dp: add custom plane ->reset hook

2017-01-30 Thread Mihail Atanassov
The reset hook needs to allocate space for a
malidp_plane_state, which is larger than drm_plane_state.
Otherwise, the hook is identical to the default one.

Signed-off-by: Mihail Atanassov 
---
 drivers/gpu/drm/arm/malidp_planes.c | 23 ++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/arm/malidp_planes.c 
b/drivers/gpu/drm/arm/malidp_planes.c
index eff2fe4..686ff86 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -58,6 +58,27 @@ static void malidp_de_plane_destroy(struct drm_plane *plane)
devm_kfree(plane->dev->dev, mp);
 }
 
+/*
+ * Replicate what the default ->reset hook does: free the state pointer and
+ * allocate a new empty object. We just need enough space to store
+ * a malidp_plane_state instead of a drm_plane_state.
+ */
+static void malidp_plane_reset(struct drm_plane *plane)
+{
+   struct malidp_plane_state *state = to_malidp_plane_state(plane->state);
+
+   if (state)
+   __drm_atomic_helper_plane_destroy_state(&state->base);
+   kfree(state);
+   plane->state = NULL;
+   state = kzalloc(sizeof(*state), GFP_KERNEL);
+   if (state) {
+   state->base.plane = plane;
+   state->base.rotation = DRM_ROTATE_0;
+   plane->state = &state->base;
+   }
+}
+
 static struct
 drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
 {
@@ -92,7 +113,7 @@ static void malidp_destroy_plane_state(struct drm_plane 
*plane,
.disable_plane = drm_atomic_helper_disable_plane,
.set_property = drm_atomic_helper_plane_set_property,
.destroy = malidp_de_plane_destroy,
-   .reset = drm_atomic_helper_plane_reset,
+   .reset = malidp_plane_reset,
.atomic_duplicate_state = malidp_duplicate_plane_state,
.atomic_destroy_state = malidp_destroy_plane_state,
 };
-- 
1.9.1



[PATCH 1/2] drm: mali-dp: Check hw version matches device-tree

2017-01-23 Thread Mihail Atanassov
Refuse to bind if the device-tree compatible string
lists a different hardware version.

Reviewed-by: Brian Starkey 
Signed-off-by: Mihail Atanassov 
---
 A couple of small improvements to driver-to-hardware binding.

 drivers/gpu/drm/arm/malidp_drv.c  | 52 +++
 drivers/gpu/drm/arm/malidp_regs.h |  2 ++
 2 files changed, 54 insertions(+)

diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 32f746e..43238f4 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -256,6 +256,46 @@ static void malidp_lastclose(struct drm_device *drm)
 };
 MODULE_DEVICE_TABLE(of, malidp_drm_of_match);
 
+static bool malidp_is_compatible_hw_id(struct malidp_hw_device *hwdev,
+  const struct of_device_id *dev_id)
+{
+   u32 core_id;
+   const char *compatstr_dp500 = "arm,mali-dp500";
+   bool is_dp500;
+   bool dt_is_dp500;
+
+   /*
+* The DP500 CORE_ID register is in a different location, so check it
+* first. If the product id field matches, then this is DP500, otherwise
+* check the DP550/650 CORE_ID register.
+*/
+   core_id = malidp_hw_read(hwdev, MALIDP500_DC_BASE + MALIDP_DE_CORE_ID);
+   /* Offset 0x18 will never read 0x500 on products other than DP500. */
+   is_dp500 = (MALIDP_PRODUCT_ID(core_id) == 0x500);
+   dt_is_dp500 = strnstr(dev_id->compatible, compatstr_dp500,
+ sizeof(dev_id->compatible)) != NULL;
+   if (is_dp500 != dt_is_dp500) {
+   DRM_ERROR("Device-tree expects %s, but hardware %s DP500.\n",
+ dev_id->compatible, is_dp500 ? "is" : "is not");
+   return false;
+   } else if (!dt_is_dp500) {
+   u16 product_id;
+   char buf[32];
+
+   core_id = malidp_hw_read(hwdev,
+MALIDP550_DC_BASE + MALIDP_DE_CORE_ID);
+   product_id = MALIDP_PRODUCT_ID(core_id);
+   snprintf(buf, sizeof(buf), "arm,mali-dp%X", product_id);
+   if (!strnstr(dev_id->compatible, buf,
+sizeof(dev_id->compatible))) {
+   DRM_ERROR("Device-tree expects %s, but hardware is 
DP%03X.\n",
+ dev_id->compatible, product_id);
+   return false;
+   }
+   }
+   return true;
+}
+
 #define MAX_OUTPUT_CHANNELS3
 
 static int malidp_bind(struct device *dev)
@@ -266,6 +306,7 @@ static int malidp_bind(struct device *dev)
struct malidp_drm *malidp;
struct malidp_hw_device *hwdev;
struct platform_device *pdev = to_platform_device(dev);
+   struct of_device_id const *dev_id;
/* number of lines for the R, G and B output */
u8 output_width[MAX_OUTPUT_CHANNELS];
int ret = 0, i;
@@ -329,6 +370,17 @@ static int malidp_bind(struct device *dev)
clk_prepare_enable(hwdev->aclk);
clk_prepare_enable(hwdev->mclk);
 
+   dev_id = of_match_device(malidp_drm_of_match, dev);
+   if (!dev_id) {
+   ret = -EINVAL;
+   goto query_hw_fail;
+   }
+
+   if (!malidp_is_compatible_hw_id(hwdev, dev_id)) {
+   ret = -EINVAL;
+   goto query_hw_fail;
+   }
+
ret = hwdev->query_hw(hwdev);
if (ret) {
DRM_ERROR("Invalid HW configuration\n");
diff --git a/drivers/gpu/drm/arm/malidp_regs.h 
b/drivers/gpu/drm/arm/malidp_regs.h
index 73fecb3..7a89997 100644
--- a/drivers/gpu/drm/arm/malidp_regs.h
+++ b/drivers/gpu/drm/arm/malidp_regs.h
@@ -92,6 +92,8 @@
 #define MALIDP_DE_H_ACTIVE(x)  (((x) & 0x1fff) << 0)
 #define MALIDP_DE_V_ACTIVE(x)  (((x) & 0x1fff) << 16)
 
+#define MALIDP_PRODUCT_ID(__core_id) ((u32)(__core_id) >> 16)
+
 /* register offsets and bits specific to DP500 */
 #define MALIDP500_DC_BASE  0x0
 #define MALIDP500_DC_CONTROL   0xc
-- 
1.8.3



[PATCH 2/2] drm: mali-dp: Check for sufficient address space

2017-01-23 Thread Mihail Atanassov
If the device-tree 'reg' node doesn't reserve enough
space for the DP, fail to bind.

Reviewed-by: Brian Starkey 
Signed-off-by: Mihail Atanassov 
---
 drivers/gpu/drm/arm/malidp_drv.c  | 20 
 drivers/gpu/drm/arm/malidp_regs.h |  2 ++
 2 files changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 43238f4..66622a5 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -296,6 +296,20 @@ static bool malidp_is_compatible_hw_id(struct 
malidp_hw_device *hwdev,
return true;
 }
 
+static bool malidp_is_sufficient_address_space(const struct resource *res,
+  const struct of_device_id 
*dev_id)
+{
+   resource_size_t res_size = resource_size(res);
+   const char *compatstr_dp500 = "arm,mali-dp500";
+
+   if (!strnstr(dev_id->compatible, compatstr_dp500,
+sizeof(dev_id->compatible)))
+   return res_size >= MALIDP550_ADDR_SPACE_SIZE;
+   else if (res_size < MALIDP500_ADDR_SPACE_SIZE)
+   return false;
+   return true;
+}
+
 #define MAX_OUTPUT_CHANNELS3
 
 static int malidp_bind(struct device *dev)
@@ -376,6 +390,12 @@ static int malidp_bind(struct device *dev)
goto query_hw_fail;
}
 
+   if (!malidp_is_sufficient_address_space(res, dev_id)) {
+   DRM_ERROR("Insufficient address space in device-tree.\n");
+   ret = -EINVAL;
+   goto query_hw_fail;
+   }
+
if (!malidp_is_compatible_hw_id(hwdev, dev_id)) {
ret = -EINVAL;
goto query_hw_fail;
diff --git a/drivers/gpu/drm/arm/malidp_regs.h 
b/drivers/gpu/drm/arm/malidp_regs.h
index 7a89997..e0651d2 100644
--- a/drivers/gpu/drm/arm/malidp_regs.h
+++ b/drivers/gpu/drm/arm/malidp_regs.h
@@ -95,6 +95,7 @@
 #define MALIDP_PRODUCT_ID(__core_id) ((u32)(__core_id) >> 16)
 
 /* register offsets and bits specific to DP500 */
+#define MALIDP500_ADDR_SPACE_SIZE  0x01000
 #define MALIDP500_DC_BASE  0x0
 #define MALIDP500_DC_CONTROL   0xc
 #define   MALIDP500_DC_CONFIG_REQ  (1 << 17)
@@ -127,6 +128,7 @@
 #define MALIDP500_CONFIG_ID0x00fd4
 
 /* register offsets and bits specific to DP550/DP650 */
+#define MALIDP550_ADDR_SPACE_SIZE  0x1
 #define MALIDP550_DE_CONTROL   0x00010
 #define MALIDP550_DE_LINE_COUNTER  0x00014
 #define MALIDP550_DE_AXI_CONTROL   0x00018
-- 
1.8.3