[PATCH 3/4] drm/dsi: Make mipi_dsi_dcs_{read, write}() symmetrical

Andrzej Hajda a.hajda at samsung.com
Tue Jul 22 02:33:11 PDT 2014


On 07/22/2014 10:12 AM, Thierry Reding wrote:
> On Tue, Jul 22, 2014 at 09:32:58AM +0200, Andrzej Hajda wrote:
>> On 07/22/2014 09:12 AM, Thierry Reding wrote:
>>> From: Thierry Reding <treding at nvidia.com>
>>>
>>> Currently the mipi_dsi_dcs_write() function requires the DCS command
>>> byte to be embedded within the write buffer whereas mipi_dsi_dcs_read()
>>> has a separate parameter. Make them more symmetrical by adding an extra
>>> command parameter to mipi_dsi_dcs_write().
>>>
>>> Also update the S6E8AA0 panel driver (the only user of this API) to
>>> adapt to this new API.
>> I do not agree with that. DCS read and write are not symmetrical by design:
>> - write just sends data,
>> - read sends data then reads response.
>>
>> Forcing API to be symmetrical complicates the implementation without real gain.
> Why does it complicate anything?

Why? Lets see:

 drivers/gpu/drm/drm_mipi_dsi.c        | 45 ++++++++++++++++++++++++-----------
 drivers/gpu/drm/panel/panel-s6e8aa0.c |  4 ++--
 include/drm/drm_mipi_dsi.h            |  4 ++--
 3 files changed, 35 insertions(+), 18 deletions(-)


Original function has two vars, one 'if', one 'switch' and one operation
call, nothing more.
You proposes to add new vars, kmalloc with no memory handling, memcpy,
playing with indices, conditional kfree. Isn't it enough to call it more
complicated? :)

>  Granted we need to dynamically allocate
> a buffer for each transfer, but it's all hidden away in a common helper
> function. The big advantage in using a separate parameter for the
> command is that it makes it trivial to implement the majority of DCS
> commands, like this:
>
> 	const u8 format = 0x77;
> 	const u8 mode = 0x00;
>
> 	mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
> 	mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format, 1);
> 	mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &mode, 1);
> 	mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);

For this I have proposed once more universal macro, sth like this:

#define mipi_dsi_dcs_write_seq(dsi, seq...) \
({\
    const u8 d[] = { seq };\
    BUILD_BUG_ON_MSG(ARRAY_SIZE(d) > 64, "DCS sequence too big for stack");\
    mipi_dsi_dcs_write(dsi, d, ARRAY_SIZE(d));\
})

It makes trivial to implement ALL DCS commands in much more readable manner.
Please compare with your examples above:
    mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SOFT_RESET);
    mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, 0x77);
    mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, 0);
    mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON);

It could be also accompanied by static version, for memory optimization:

#define mipi_dsi_dcs_write_seq_static(dsi, seq...) \
({\
    static const u8 d[] = { seq };\
    mipi_dsi_dcs_write(dsi, d, ARRAY_SIZE(d));\
})


>
> Without the extra parameter, the above becomes:
>
> 	const u8 data[1] = { MIPI_DCS_SOFT_RESET };
> 	mipi_dsi_dcs_write(dsi, data, sizeof(data));
>
> 	const u8 data[2] = { MIPI_DCS_SET_PIXEL_FORMAT, 0x77 };
> 	mipi_dsi_dcs_write(dsi, data, sizeof(data));
>
> 	const u8 data[2] = { MIPI_DCS_SET_TEAR_ON, 0x00 };
> 	mipi_dsi_dcs_write(dsi, data, sizeof(data));
>
> 	const u8 data[1] = { MIPI_DCS_SET_DISPLAY_ON };
> 	mipi_dsi_dcs_write(dsi, data, sizeof(data));
>
> In this form it looks still rather readable, but if you need to do this
> within an initialization function, it become fairly cluttered:
>
> 	const u8 soft_reset[1] = { MIPI_DCS_SOFT_RESET };
> 	const u8 set_pixel_format[2] = { MIPI_DCS_SET_PIXEL_FORMAT, 0x77 };
> 	const u8 set_tear_on[2] = { MIPI_DCS_SET_TEAR_ON, 0x00 };
> 	const u8 set_display_on[1] = { MIPI_DCS_SET_DISPLAY_ON };
>
> 	mipi_dsi_dcs_write(dsi, soft_reset, sizeof(soft_reset));
>
> 	mipi_dsi_dcs_write(dsi, set_pixel_format, sizeof(set_pixel_format));
>
> 	mipi_dsi_dcs_write(dsi, set_tear_on, sizeof(set_tear_on));
>
> 	mipi_dsi_dcs_write(dsi, set_display_on, sizeof(set_display_on));
>
> I find that really hard to read because it has a potentially large gap
> between the place where the commands are defined and where they're used.

You will have the same gap issue with your approach in case of DCS
commands with arguments.
With 'my' approach it is still readable.

>
> Some of this could possibly be alleviated by adding separate functions
> for standard commands. But either way, I think having this kind of
> symmetry within an API is always good (it's consistent). By the law of
> least surprise people will actually expect mipi_dsi_dcs_write() to take
> a command as a second parameter.

As I wrote earlier I do not see symmetry here: dcs-read is in fact write
and read,
dcs-write is just write. Hiding this fact in API does not seems to me
good, but I guess
it is rather matter of taste.

Regards
Andrzej

>
> Thierry



More information about the dri-devel mailing list