drm/i2c: adv7511: ADV7533 support
Subsystems (5)
cover drm/i2c: adv7511: ADV7533 support
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
This series adds support for ADV7533. Unlike ADV7511 that's modelled as a drm i2c slave encoder, ADV7533 is a drm_bridge object. The bridge ops further create a HDMI type connector device for the chip's output.
In order to pass DSI specific parameters to the host, the driver creates a dummy DSI device, which it registers to a DSI host as specified via DT.
The first patch in the series is a minor fix, the rest add ADV7533 support. They depend on the series I posted sometime back:
"drm/dsi: DSI for devices with different control bus"
https://lkml.org/lkml/2015/6/30/42
Archit Taneja (4):
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Refactor encoder slave functions drm/i2c: adv7511: Add drm_bridge/connector for ADV7533 drm/i2c: adv7511: Create mipi_dsi_device for ADV7533
Lars-Peter Clausen (1):
drm/i2c: adv7511: Initial support for adv7533
drivers/gpu/drm/i2c/adv7511.c | 486 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 437 insertions(+), 49 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 1/5 drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled
When the adv7511 i2c client doesn't have an interrupt line, we observe a deadlock on caused by trying to lock drm device's mode_config.mutex twice in the same context.
Here is the sequence that causes it:
ioctl DRM_IOCTL_MODE_GETCONNECTOR from userspace
drm_mode_getconnector (acquires mode_config mutex)
connector->fill_modes()
drm_helper_probe_single_connector_modes
connector_funcs->get_modes
adv7511_encoder_get_modes
adv7511_get_edid_block
adv7511_irq_process
drm_helper_hpd_irq_event (acquires mode_config mutex again)In adv7511_irq_process, don't call drm_helper_hpd_irq_event when not called from interrupt context. It doesn't serve any purpose there anyway.
--- drivers/gpu/drm/i2c/adv7511.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +4 -4
@@ -422,7 +422,7 @@ static bool adv7511_hpd(struct adv7511 *adv7511)return false; } -static int adv7511_irq_process (struct adv7511 *adv7511) +static int adv7511_irq_process (struct adv7511 *adv7511,bool process_hpd) {unsigned int irq0, irq1;int ret;
@@ -438,7 +438,7 @@ static int adv7511_irq_process(struct adv7511 *adv7511)regmap_write (adv7511->regmap,ADV7511_REG_INT (0 ), irq0);regmap_write (adv7511->regmap,ADV7511_REG_INT (1 ), irq1); -if (irq0 &ADV7511_INT0_HDP && adv7511->encoder) +if (process_hpd && irq0 &ADV7511_INT0_HDP && adv7511->encoder)drm_helper_hpd_irq_event (adv7511->encoder->dev);if (irq0 &ADV7511_INT0_EDID_READY || irq1 &ADV7511_INT1_DDC_ERROR ) {
@@ -456,7 +456,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid)struct adv7511 *adv7511 = devid;int ret; - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, true);return ret <0 ?IRQ_NONE :IRQ_HANDLED ; }
@@ -473,7 +473,7 @@ static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout) adv7511->edid_read, msecs_to_jiffies(timeout)); }else {for (; timeout >0 ; timeout -=25 ) { - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, false);if (ret <0 )break ;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 2/5 drm/i2c: adv7511: Initial support for adv7533
In reply to Archit TanejaFrom: Lars-Peter Clausen <[email protected]>
ADV7533 is a DSI to HDMI encoder chip. It is a derivative of ADV7511, with additional blocks to translate input DSI data to parallel RGB data. Besides the ADV7511 i2c register map, it has additional registers that require to be configured to activate the DSI blocks.
Use DT compatible strings to populate the adv7533 type enum. Add minimal register configurations belonging to the DSI/CEC register map.
--- drivers/gpu/drm/i2c/adv7511.c | 155 +++++++++++++++++++++++++++++++++++------- 1 file changed, 131 insertions(+), 24 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +131 -24
@@ -20,12 +20,18 @@#include "adv7511.h" +enum adv7511_type { +ADV7511 , +ADV7533 , +}; +struct adv7511 {struct i2c_client *i2c_main;struct i2c_client *i2c_edid; +struct i2c_client *i2c_cec;struct regmap *regmap; -struct regmap *packet_memory_regmap; +struct regmap *regmap_cec;enum drm_connector_status status;bool powered;
@@ -46,6 +52,8 @@ struct adv7511 {struct edid *edid;struct gpio_desc *gpio_pd; + +enum adv7511_type type; };static struct adv7511 *encoder_to_adv7511 (struct drm_encoder *encoder)
@@ -66,6 +74,23 @@ static const struct reg_default adv7511_fixed_registers[] = { { 0x55, 0x02 }, }; +/* ADI recommended values for proper operation. */ +static const struct reg_default adv7533_fixed_registers[] = { + {0x16 ,0x20 }, + {0x9a ,0xe0 }, + {0xba ,0x70 }, + {0xde ,0x82 }, + {0xe4 ,0x40 }, + {0xe5 ,0x80 }, +}; + +static const struct reg_default adv7533_cec_fixed_registers[] = { + {0x15 ,0xd0 }, + {0x17 ,0xd0 }, + {0x24 ,0x20 }, + {0x57 ,0x11 }, +}; +/* ----------------------------------------------------------------------------- * Register access */
@@ -158,6 +183,15 @@ static const struct regmap_config adv7511_regmap_config = { .volatile_reg = adv7511_register_volatile, }; +static const struct regmap_config adv7533_cec_regmap_config = { + .reg_bits =8 , + .val_bits =8 , + + .max_register =0xff , + .cache_type =REGCACHE_RBTREE , +}; + +/* ----------------------------------------------------------------------------- * Hardware configuration */
@@ -358,6 +392,25 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, adv7511->rgb = config->input_colorspace ==HDMI_COLORSPACE_RGB ; } +static void adv7511_dsi_receiver_dpms (struct adv7511 *adv7511) +{ +if (adv7511->type !=ADV7533 ) +return ; + +if (adv7511->powered) { +/* set number of dsi lanes (hardcoded to 4 for now) */ +regmap_write (adv7511->regmap_cec,0x1c ,0x4 <<4 ); +/* disable internal timing generator */ +regmap_write (adv7511->regmap_cec,0x27 ,0x0b ); +/* enable hdmi */ +regmap_write (adv7511->regmap_cec,0x03 ,0x89 ); +/* disable test mode */ +regmap_write (adv7511->regmap_cec,0x55 ,0x00 ); + }else { +regmap_write (adv7511->regmap_cec,0x03 ,0x0b ); + } +} +static void adv7511_power_on (struct adv7511 *adv7511) { adv7511->current_edid_segment =-1 ;
@@ -387,6 +440,8 @@ static void adv7511_power_on(struct adv7511 *adv7511)regcache_sync (adv7511->regmap); adv7511->powered = true; + +adv7511_dsi_receiver_dpms (adv7511); }static void adv7511_power_off (struct adv7511 *adv7511)
@@ -398,6 +453,8 @@ static void adv7511_power_off(struct adv7511 *adv7511)regcache_mark_dirty (adv7511->regmap); adv7511->powered = false; + +adv7511_dsi_receiver_dpms (adv7511); }/* -----------------------------------------------------------------------------
@@ -567,6 +624,9 @@ static int adv7511_get_modes(struct drm_encoder *encoder,/* Reading the EDID only works if the device is powered */ if (!adv7511->powered) { +regmap_update_bits (adv7511->regmap,ADV7511_REG_POWER2 , +ADV7511_REG_POWER2_HDP_SRC_MASK , +ADV7511_REG_POWER2_HDP_SRC_NONE );regmap_write (adv7511->regmap,ADV7511_REG_INT (0 ),ADV7511_INT0_EDID_READY ); regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
@@ -770,8 +830,6 @@ static int adv7511_parse_dt(struct device_node *np,const char *str;int ret; -memset (config,0 ,sizeof (*config)); -of_property_read_u32 (np,"adi,input-depth" , &config->input_color_depth);if (config->input_color_depth !=8 && config->input_color_depth !=10 && config->input_color_depth !=12 )
@@ -853,6 +911,15 @@ static const int edid_i2c_addr = 0x7e;static const int packet_i2c_addr =0x70 ;static const int cec_i2c_addr =0x78 ; +static const struct of_device_id adv7511_of_ids[] = { + { .compatible ="adi,adv7511" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7511w" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7513" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7533" , .data = (void *)ADV7533 }, + { } +}; +MODULE_DEVICE_TABLE (of, adv7511_of_ids); +static int adv7511_probe (struct i2c_client *i2c,const struct i2c_device_id *id) {struct adv7511_link_config link_config;
@@ -871,9 +938,22 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) adv7511->powered = false; adv7511->status = connector_status_disconnected; - ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; +if (dev->of_node) { +const struct of_device_id *of_id; + + of_id =of_match_node (adv7511_of_ids, dev->of_node); + adv7511->type = (enum adv7511_type ) of_id->data; + }else { + adv7511->type = id->driver_data; + } + +memset (&link_config,0 ,sizeof (link_config)); + +if (adv7511->type ==ADV7511 ) { + ret =adv7511_parse_dt (dev->of_node, &link_config); +if (ret) +return ret; + }/* * The power down GPIO is optional. If present, toggle it from active to
@@ -897,10 +977,19 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)return ret;dev_dbg (dev,"Rev. %d\n" , val); - ret =regmap_register_patch (adv7511->regmap, adv7511_fixed_registers, -ARRAY_SIZE (adv7511_fixed_registers)); -if (ret) -return ret; +if (adv7511->type ==ADV7511 ) { + ret =regmap_register_patch (adv7511->regmap, + adv7511_fixed_registers, +ARRAY_SIZE (adv7511_fixed_registers)); +if (ret) +return ret; + }else { + ret =regmap_register_patch (adv7511->regmap, + adv7533_fixed_registers, +ARRAY_SIZE (adv7533_fixed_registers)); +if (ret) +return ret; + }regmap_write (adv7511->regmap,ADV7511_REG_EDID_I2C_ADDR , edid_i2c_addr); regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
@@ -913,6 +1002,27 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)if (!adv7511->i2c_edid)return -ENOMEM ; + adv7511->i2c_cec =i2c_new_dummy (i2c->adapter, cec_i2c_addr >>1 ); +if (!adv7511->i2c_cec) { + ret = -ENOMEM ; + goto err_i2c_unregister_edid; + } + + adv7511->regmap_cec =devm_regmap_init_i2c (adv7511->i2c_cec, + &adv7533_cec_regmap_config); +if (IS_ERR (adv7511->regmap_cec)) { + ret =PTR_ERR (adv7511->regmap_cec); + goto err_i2c_unregister_cec; + } + +if (adv7511->type ==ADV7533 ) { + ret =regmap_register_patch (adv7511->regmap_cec, + adv7533_cec_fixed_registers, +ARRAY_SIZE (adv7533_cec_fixed_registers)); +if (ret) +return ret; + } +if (i2c->irq) {init_waitqueue_head (&adv7511->wq);
@@ -921,7 +1031,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)IRQF_ONESHOT ,dev_name (dev), adv7511);if (ret) - goto err_i2c_unregister_device; + goto err_i2c_unregister_cec; }/* CEC is unused for now */
@@ -932,11 +1042,14 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)i2c_set_clientdata (i2c, adv7511); -adv7511_set_link_config (adv7511, &link_config); +if (adv7511->type ==ADV7511 ) +adv7511_set_link_config (adv7511, &link_config);return 0 ; -err_i2c_unregister_device: +err_i2c_unregister_cec: +i2c_unregister_device (adv7511->i2c_cec); +err_i2c_unregister_edid:i2c_unregister_device (adv7511->i2c_edid);return ret;
@@ -946,6 +1059,7 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +i2c_unregister_device (adv7511->i2c_cec);i2c_unregister_device (adv7511->i2c_edid);kfree (adv7511->edid);
@@ -968,21 +1082,14 @@ static int adv7511_encoder_init(struct i2c_client *i2c, struct drm_device *dev, }static const struct i2c_device_id adv7511_i2c_ids[] = { - {"adv7511" ,0 }, - {"adv7511w" ,0 }, - {"adv7513" ,0 }, + {"adv7511" ,ADV7511 }, + {"adv7511w" ,ADV7511 }, + {"adv7513" ,ADV7511 }, + {"adv7533" ,ADV7533 }, { } };MODULE_DEVICE_TABLE (i2c, adv7511_i2c_ids); -static const struct of_device_id adv7511_of_ids[] = { - { .compatible ="adi,adv7511" , }, - { .compatible ="adi,adv7511w" , }, - { .compatible ="adi,adv7513" , }, - { } -}; -MODULE_DEVICE_TABLE (of, adv7511_of_ids); -static struct drm_i2c_encoder_driver adv7511_driver = { .i2c_driver = { .driver = {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH 2/5] drm/i2c: adv7511: Initial support for adv7533
Quoted 2 lines · Archit Taneja
From: Lars-Peter Clausen <[email protected]>
[..]
Quoted 1 line
drivers/gpu/drm/i2c/adv7511.c +0
-0
[..]
drivers/gpu/drm/i2c/adv7511.c static const int edid_i2c_addr = 0x7e; · line 921
Quoted 9 lines
drivers/gpu/drm/i2c/adv7511.c +8
-0+static const struct of_device_id adv7511_of_ids[] = { + { .compatible ="adi,adv7511" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7511w" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7513" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7533" , .data = (void *)ADV7533 }, + { } +}; +MODULE_DEVICE_TABLE (of, adv7511_of_ids);
Please leave this at the bottom.
Quoted 5 lines
drivers/gpu/drm/i2c/adv7511.c +1
-0+static int adv7511_probe (struct i2c_client *i2c,const struct i2c_device_id *id) {struct adv7511_link_config link_config;
drivers/gpu/drm/i2c/adv7511.c static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) · line 944
Quoted 10 lines
drivers/gpu/drm/i2c/adv7511.c +4
-3@@ -871,9 +938,22 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) adv7511->powered = false; adv7511->status = connector_status_disconnected; - ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; +if (dev->of_node) { +const struct of_device_id *of_id; + + of_id =of_match_node (adv7511_of_ids, dev->of_node);
If you use of_device_get_match_data() instead you don't need to move the of_device_id table.
Quoted 5 lines
drivers/gpu/drm/i2c/adv7511.c +5
-0+ adv7511->type = (enum adv7511_type ) of_id->data; + }else { + adv7511->type = id->driver_data; + } +
[..]
Quoted 11 lines
static const struct
i2c_device_idadv7511_i2c_ids[] = {drivers/gpu/drm/i2c/adv7511.c +4
-3- { "adv7511", 0 }, - { "adv7511w", 0 }, - { "adv7513", 0 }, + { "adv7511", ADV7511 }, + { "adv7511w", ADV7511 }, + { "adv7513", ADV7511 }, + { "adv7533", ADV7533 }, { } };
drivers/gpu/drm/i2c/adv7511.c static int adv7511_encoder_init(struct i2c_client *i2c, struct drm_device *dev, · line 985
Quoted 10 lines
drivers/gpu/drm/i2c/adv7511.c +0
-8MODULE_DEVICE_TABLE (i2c, adv7511_i2c_ids); -static const struct of_device_id adv7511_of_ids[] = { - { .compatible ="adi,adv7511" , }, - { .compatible ="adi,adv7511w" , }, - { .compatible ="adi,adv7513" , }, - { } -}; -MODULE_DEVICE_TABLE (of, adv7511_of_ids); -
Regards,
Bjorn
Re: [PATCH 2/5] drm/i2c: adv7511: Initial support for adv7533
Quoted 29 lines · Bjorn Andersson
Quoted 2 lines · Archit Taneja
From: Lars-Peter Clausen <[email protected]>
[..]
Quoted 1 line
drivers/gpu/drm/i2c/adv7511.c +0
-0[..]
drivers/gpu/drm/i2c/adv7511.c static const int edid_i2c_addr = 0x7e; · line 921
Quoted 9 lines
drivers/gpu/drm/i2c/adv7511.c +8
-0+static const struct of_device_id adv7511_of_ids[] = { + { .compatible ="adi,adv7511" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7511w" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7513" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7533" , .data = (void *)ADV7533 }, + { } +}; +MODULE_DEVICE_TABLE (of, adv7511_of_ids);Please leave this at the bottom.
Quoted 8 lines
drivers/gpu/drm/i2c/adv7511.c +1
-0+static int adv7511_probe (struct i2c_client *i2c,const struct i2c_device_id *id) {struct adv7511_link_config link_config;@@ -871,9 +938,22 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) adv7511->powered = false; adv7511->status = connector_status_disconnected;
Quoted 10 lines
drivers/gpu/drm/i2c/adv7511.c static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) · line 944
Quoted 7 lines
drivers/gpu/drm/i2c/adv7511.c +4
-3- ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; +if (dev->of_node) { +const struct of_device_id *of_id; + + of_id =of_match_node (adv7511_of_ids, dev->of_node);If you use
of_device_get_match_data()instead you don't need to move theof_device_idtable.
Thanks, will use this in future revisions.
Archit
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH 3/5 drm/i2c: adv7511: Refactor encoder slave functions
In reply to Archit TanejaADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Move the code in encoder slave functions to generate helpers that are agnostic to the drm object type. These helpers will later also be used by bridge and connecter helper functions.
--- drivers/gpu/drm/i2c/adv7511.c | 80 ++++++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 23 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +57 -23
@@ -612,13 +612,11 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, }/* ----------------------------------------------------------------------------- -* Encoder operations +* ADV75xx helpers */ - -static int adv7511_get_modes (struct drm_encoder *encoder, -struct drm_connector *connector) +static int adv7511_get_modes (struct adv7511 *adv7511, +struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);struct edid *edid;unsigned int count;
@@ -656,21 +654,10 @@ static int adv7511_get_modes(struct drm_encoder *encoder,return count; } -static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) -{ -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); - -if (mode ==DRM_MODE_DPMS_ON ) -adv7511_power_on (adv7511); -else -adv7511_power_off (adv7511); -} -static enum drm_connector_status -adv7511_encoder_detect (struct drm_encoder *encoder, +adv7511_detect (struct adv7511 *adv7511,struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);enum drm_connector_status status;unsigned int val;bool hpd;
@@ -694,7 +681,7 @@ adv7511_encoder_detect(struct drm_encoder *encoder,if (status == connector_status_connected && hpd && adv7511->powered) {regcache_mark_dirty (adv7511->regmap);adv7511_power_on (adv7511); -adv7511_get_modes (encoder, connector); +adv7511_get_modes (adv7511, connector);if (adv7511->status == connector_status_connected) status = connector_status_disconnected; }else {
@@ -708,8 +695,8 @@ adv7511_encoder_detect(struct drm_encoder *encoder,return status; } -static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, -struct drm_display_mode *mode) +static int adv7511_mode_valid (struct adv7511 *adv7511, +const struct drm_display_mode *mode) {if (mode->clock >165000 )return MODE_CLOCK_HIGH ;
@@ -717,11 +704,10 @@ static int adv7511_encoder_mode_valid(struct drm_encoder *encoder,return MODE_OK ; } -static void adv7511_encoder_mode_set (struct drm_encoder *encoder, +static void adv7511_mode_set (struct adv7511 *adv7511,struct drm_display_mode *mode,struct drm_display_mode *adj_mode) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);unsigned int low_refresh_rate;unsigned int hsync_polarity =0 ;unsigned int vsync_polarity =0 ;
@@ -812,12 +798,60 @@ static void adv7511_encoder_mode_set(struct drm_encoder *encoder, adv7511->f_tmds = mode->clock; } +/* ----------------------------------------------------------------------------- +* Encoder operations +*/ + +static int adv7511_encoder_get_modes (struct drm_encoder *encoder, +struct drm_connector *connector) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_get_modes (adv7511, connector); +} + +static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +if (mode ==DRM_MODE_DPMS_ON ) +adv7511_power_on (adv7511); +else +adv7511_power_off (adv7511); +} + +static enum drm_connector_status +adv7511_encoder_detect (struct drm_encoder *encoder, +struct drm_connector *connector) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_detect (adv7511, connector); +} + +static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, +struct drm_display_mode *mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_mode_valid (adv7511, mode); +} + +static void adv7511_encoder_mode_set (struct drm_encoder *encoder, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +adv7511_mode_set (adv7511, mode, adj_mode); +} +static struct drm_encoder_slave_funcs adv7511_encoder_funcs = { .dpms = adv7511_encoder_dpms, .mode_valid = adv7511_encoder_mode_valid, .mode_set = adv7511_encoder_mode_set, .detect = adv7511_encoder_detect, - .get_modes = adv7511_get_modes, + .get_modes = adv7511_encoder_get_modes, };/* -----------------------------------------------------------------------------
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Laurent Pinchart
reviewerRe: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Hi Archit,
(CC'ing Boris Brezillon)
Thank you for the patch.
Quoted 3 lines · On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
Boris, I know you were experimenting with that, do you have anything to report ?
Quoted 152 lines
Move the code in encoder slave functions to generate helpers that are agnostic to the drm object type. These helpers will later also be used by bridge and connecter helper functions.
Signed-off-by Archit Taneja <[email protected]>--- drivers/gpu/drm/i2c/adv7511.c | 80 +++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 23 deletions(-)drivers/gpu/drm/i2c/adv7511.c +56
-28@@ -612,13 +612,11 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, }/* --------------------------------------------------------------------------- -- - * Encoder operations +* ADV75xx helpers */ - -static int adv7511_get_modes (struct drm_encoder *encoder, -struct drm_connector *connector) +static int adv7511_get_modes (struct adv7511 *adv7511, +struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);struct edid *edid;unsigned int count;@@ -656,21 +654,10 @@ static int adv7511_get_modes(struct drm_encoder *encoder, return count; } -static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) -{ -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); - -if (mode ==DRM_MODE_DPMS_ON ) -adv7511_power_on (adv7511); -else -adv7511_power_off (adv7511); -} -static enum drm_connector_status -adv7511_encoder_detect (struct drm_encoder *encoder, +adv7511_detect (struct adv7511 *adv7511,struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);enum drm_connector_status status;unsigned int val;bool hpd;@@ -694,7 +681,7 @@ adv7511_encoder_detect(struct drm_encoder *encoder,if (status == connector_status_connected && hpd && adv7511->powered) {regcache_mark_dirty (adv7511->regmap);adv7511_power_on (adv7511); -adv7511_get_modes (encoder, connector); +adv7511_get_modes (adv7511, connector);if (adv7511->status == connector_status_connected) status = connector_status_disconnected; }else {@@ -708,8 +695,8 @@ adv7511_encoder_detect(struct drm_encoder *encoder,return status; } -static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, -struct drm_display_mode *mode) +static int adv7511_mode_valid (struct adv7511 *adv7511, +const struct drm_display_mode *mode) {if (mode->clock >165000 )return MODE_CLOCK_HIGH ;@@ -717,11 +704,10 @@ static int adv7511_encoder_mode_valid(struct drm_encoder *encoder, return MODE_OK; } -static void adv7511_encoder_mode_set (struct drm_encoder *encoder, +static void adv7511_mode_set (struct adv7511 *adv7511,struct drm_display_mode *mode,struct drm_display_mode *adj_mode) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);unsigned int low_refresh_rate;unsigned int hsync_polarity =0 ;unsigned int vsync_polarity =0 ;@@ -812,12 +798,60 @@ static void adv7511_encoder_mode_set(struct drm_encoder *encoder, adv7511->f_tmds = mode->clock; } +/* --------------------------------------------------------------------------- -- + * Encoder operations +*/ + +static int adv7511_encoder_get_modes (struct drm_encoder *encoder, +struct drm_connector *connector) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_get_modes (adv7511, connector); +} + +static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +if (mode ==DRM_MODE_DPMS_ON ) +adv7511_power_on (adv7511); +else +adv7511_power_off (adv7511); +} + +static enum drm_connector_status +adv7511_encoder_detect (struct drm_encoder *encoder, +struct drm_connector *connector) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_detect (adv7511, connector); +} + +static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, +struct drm_display_mode *mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_mode_valid (adv7511, mode); +} + +static void adv7511_encoder_mode_set (struct drm_encoder *encoder, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +adv7511_mode_set (adv7511, mode, adj_mode); +} +static struct drm_encoder_slave_funcs adv7511_encoder_funcs = { .dpms = adv7511_encoder_dpms, .mode_valid = adv7511_encoder_mode_valid, .mode_set = adv7511_encoder_mode_set, .detect = adv7511_encoder_detect, - .get_modes = adv7511_get_modes, + .get_modes = adv7511_encoder_get_modes, };/* --------------------------------------------------------------------------- --
Signature · 3 lines
Regards, Laurent Pinchart
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Hi,
Quoted 7 lines · Laurent Pinchart
Hi Archit,
(CC'ing Boris Brezillon)
Thank you for the patch.
On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
Quoted 8 lines
Quoted 3 lines
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
i2c slave encoders and bridges aren't exactly the same. slave encoders are used when the there is no real 'encoder' in the display chain. bridges are used when there is already an encoder available, and the bridge entity represents another encoder in the chain.
ADV7511 takes in RGB/MIPI DPI data, which is generally the output of a crtc for drm drivers.
ADV7533 takes in MIPI DSI data, which is generally the output of an encoder for drm drivers.
Therefore, having i2c slave encoder for the former and bridge for the latter made sense to me.
I do agree that it would be better if they were somehow merged. It would prevent the fragmentation we currently have among encoder chips.
One possible way would be to convert slave encoder to bridge. With this, an i2c slave encoder would be a 'dummy encoder' and a bridge. i2c slave encoders even now just tie the slave encoder helper funcs to encoder helper funcs. So it's not really any different.
Merging these 2 entities would be nice, but we're still shying away from the larger problem of creating generic encoder chains. The ideal solution would be for bridges and slave encoders to just be 'encoders', and the facility to connect on encoder output to the input of another. I don't know how easy it is to do this, and whether it'll break userspace.
Archit
Quoted 157 lines
Boris, I know you were experimenting with that, do you have anything to report ?
Quoted 152 lines
Move the code in encoder slave functions to generate helpers that are agnostic to the drm object type. These helpers will later also be used by bridge and connecter helper functions.
Signed-off-by Archit Taneja <[email protected]>--- drivers/gpu/drm/i2c/adv7511.c | 80 +++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 23 deletions(-)drivers/gpu/drm/i2c/adv7511.c +56
-28@@ -612,13 +612,11 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, }/* --------------------------------------------------------------------------- -- - * Encoder operations +* ADV75xx helpers */ - -static int adv7511_get_modes (struct drm_encoder *encoder, -struct drm_connector *connector) +static int adv7511_get_modes (struct adv7511 *adv7511, +struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);struct edid *edid;unsigned int count;@@ -656,21 +654,10 @@ static int adv7511_get_modes(struct drm_encoder *encoder, return count; } -static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) -{ -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); - -if (mode ==DRM_MODE_DPMS_ON ) -adv7511_power_on (adv7511); -else -adv7511_power_off (adv7511); -} -static enum drm_connector_status -adv7511_encoder_detect (struct drm_encoder *encoder, +adv7511_detect (struct adv7511 *adv7511,struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);enum drm_connector_status status;unsigned int val;bool hpd;@@ -694,7 +681,7 @@ adv7511_encoder_detect(struct drm_encoder *encoder,if (status == connector_status_connected && hpd && adv7511->powered) {regcache_mark_dirty (adv7511->regmap);adv7511_power_on (adv7511); -adv7511_get_modes (encoder, connector); +adv7511_get_modes (adv7511, connector);if (adv7511->status == connector_status_connected) status = connector_status_disconnected; }else {@@ -708,8 +695,8 @@ adv7511_encoder_detect(struct drm_encoder *encoder,return status; } -static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, -struct drm_display_mode *mode) +static int adv7511_mode_valid (struct adv7511 *adv7511, +const struct drm_display_mode *mode) {if (mode->clock >165000 )return MODE_CLOCK_HIGH ;@@ -717,11 +704,10 @@ static int adv7511_encoder_mode_valid(struct drm_encoder *encoder, return MODE_OK; } -static void adv7511_encoder_mode_set (struct drm_encoder *encoder, +static void adv7511_mode_set (struct adv7511 *adv7511,struct drm_display_mode *mode,struct drm_display_mode *adj_mode) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);unsigned int low_refresh_rate;unsigned int hsync_polarity =0 ;unsigned int vsync_polarity =0 ;@@ -812,12 +798,60 @@ static void adv7511_encoder_mode_set(struct drm_encoder *encoder, adv7511->f_tmds = mode->clock; } +/* --------------------------------------------------------------------------- -- + * Encoder operations +*/ + +static int adv7511_encoder_get_modes (struct drm_encoder *encoder, +struct drm_connector *connector) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_get_modes (adv7511, connector); +} + +static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +if (mode ==DRM_MODE_DPMS_ON ) +adv7511_power_on (adv7511); +else +adv7511_power_off (adv7511); +} + +static enum drm_connector_status +adv7511_encoder_detect (struct drm_encoder *encoder, +struct drm_connector *connector) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_detect (adv7511, connector); +} + +static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, +struct drm_display_mode *mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_mode_valid (adv7511, mode); +} + +static void adv7511_encoder_mode_set (struct drm_encoder *encoder, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +adv7511_mode_set (adv7511, mode, adj_mode); +} +static struct drm_encoder_slave_funcs adv7511_encoder_funcs = { .dpms = adv7511_encoder_dpms, .mode_valid = adv7511_encoder_mode_valid, .mode_set = adv7511_encoder_mode_set, .detect = adv7511_encoder_detect, - .get_modes = adv7511_get_modes, + .get_modes = adv7511_encoder_get_modes, };/* --------------------------------------------------------------------------- --
Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Archit, Laurent,
Quoted 42 lines · On Tue, 28 Jul 2015 13:47:37 +0530 Archit Taneja <[email protected]> wrote:
Hi,
Quoted 7 lines · Laurent Pinchart
Hi Archit,
(CC'ing Boris Brezillon)
Thank you for the patch.
On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
Quoted 8 lines
Quoted 3 lines
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
i2c slave encoders and bridges aren't exactly the same. slave encoders are used when the there is no real 'encoder' in the display chain. bridges are used when there is already an encoder available, and the bridge entity represents another encoder in the chain.
ADV7511 takes in RGB/MIPI DPI data, which is generally the output of a crtc for drm drivers.
ADV7533 takes in MIPI DSI data, which is generally the output of an encoder for drm drivers.
Therefore, having i2c slave encoder for the former and bridge for the latter made sense to me.
I do agree that it would be better if they were somehow merged. It would prevent the fragmentation we currently have among encoder chips.
One possible way would be to convert slave encoder to bridge. With this, an i2c slave encoder would be a 'dummy encoder' and a bridge. i2c slave encoders even now just tie the slave encoder helper funcs to encoder helper funcs. So it's not really any different.
Quoted 6 lines
Merging these 2 entities would be nice, but we're still shying away from the larger problem of creating generic encoder chains. The ideal solution would be for bridges and slave encoders to just be 'encoders', and the facility to connect on encoder output to the input of another. I don't know how easy it is to do this, and whether it'll break userspace.
Yes, that's pretty much what I was trying to do.
I'd also like to ease display pipelines creation by providing helper functions, so that display controller don't have to worry about encoders and connectors creation if these ones are attached to external encoders.
Quoted 6 lines
Archit
Quoted 3 lines
Boris, I know you were experimenting with that, do you have anything to report ?
Nope, I didn't work on it since last time we talked about it. I pushed my work here if you want to have a look [1].
Best Regards,
Boris
[1]https://github.com/bbrezillon/linux-at91/tree/drm-encoder-chain-WIP
Signature · 7 lines
Boris Brezillon, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Hi Boris, Laurent,
Quoted 60 lines · Boris Brezillon
Archit, Laurent,
Quoted 42 lines · On Tue, 28 Jul 2015 13:47:37 +0530 Archit Taneja <[email protected]> wrote:
Hi,
Quoted 7 lines · Laurent Pinchart
Hi Archit,
(CC'ing Boris Brezillon)
Thank you for the patch.
On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
Quoted 8 lines
Quoted 3 lines
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
i2c slave encoders and bridges aren't exactly the same. slave encoders are used when the there is no real 'encoder' in the display chain. bridges are used when there is already an encoder available, and the bridge entity represents another encoder in the chain.
ADV7511 takes in RGB/MIPI DPI data, which is generally the output of a crtc for drm drivers.
ADV7533 takes in MIPI DSI data, which is generally the output of an encoder for drm drivers.
Therefore, having i2c slave encoder for the former and bridge for the latter made sense to me.
I do agree that it would be better if they were somehow merged. It would prevent the fragmentation we currently have among encoder chips.
One possible way would be to convert slave encoder to bridge. With this, an i2c slave encoder would be a 'dummy encoder' and a bridge. i2c slave encoders even now just tie the slave encoder helper funcs to encoder helper funcs. So it's not really any different.
Quoted 6 lines
Merging these 2 entities would be nice, but we're still shying away from the larger problem of creating generic encoder chains. The ideal solution would be for bridges and slave encoders to just be 'encoders', and the facility to connect on encoder output to the input of another. I don't know how easy it is to do this, and whether it'll break userspace.
Yes, that's pretty much what I was trying to do.
I'd also like to ease display pipelines creation by providing helper functions, so that display controller don't have to worry about encoders and connectors creation if these ones are attached to external encoders.Quoted 1 line
Quoted 8 lines
Quoted 5 lines
Archit
Quoted 3 lines
Boris, I know you were experimenting with that, do you have anything to report ?
Nope, I didn't work on it since last time we talked about it. I pushed my work here if you want to have a look [1].
I went through the branch you shared. From what I understood, the encoder chain comprises of one 'real' encoder object (drm_encoder) in the 'drm_encoder_chain' struct. This drm_encoder encapsulates all the 'encoder elements' forming the chain.
I'm guessing the various dridge/slave encoder drivers would have to be changed to now create a drm_encoder_element object, replacing drm_bridge/drm_i2c_slave_encoder objects.
One problem I see with this approach is that we can't use this when the display controller already exposes a drm_encoder. I.e, it already creates a drm_encoder object. If we want the encoder chain to be connected to the output of this encoder, we'll need to link the 2 drm_encoders together, which isn't possible at the moment.
I guess we have two ways to go about this:
1) Have an approach like this where all the entities in the encoder chain connect to just one encoder. We define the sequence in which they are connected. The drm kms framework acts as if this chain doesn't exist, and assumes that this is what the encoder is outputting.
2) Make each element in the chain be a 'drm_encoder' object in itself. This would be a more intrusive change, since drm_encoders are expected to receive an input from crtc, and output to a connector. Furthermore, it may confuse userspace what encoder to chose.
For 1), we could either work more on your approach, or use drm_bridges. drm_bridges can already be chained to each other, and bridge ops of each bridge in the chain are called successively. It still relies on the device drivers to form the chain, which is something your
approach takes care of by itself. But that's something that can be
extended for bridges too.
Laurent,
Merging i2c slave encoders and bridges is possible, but there is no guarantee that the new solution would be future proof and work well with encoder chains. We needed more consensus from folks on dri-devel.
For ADV7533, could you please look at the other parts? Especially the one that creates a dummy mipi DSI device, and connecting to a dsi host. I'd previously posted a RFC to enable that:
http://lkml.iu.edu/hypermail/linux/kernel/1506.3/03249.html
Archit
Quoted 9 lines
Best Regards,
Boris
[1]https://github.com/bbrezillon/linux-at91/tree/drm-encoder-chain-WIP
Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Hi Archit,
Quoted 81 lines · On Fri, 31 Jul 2015 10:56:20 +0530 Archit Taneja <[email protected]> wrote:
Hi Boris, Laurent,
Quoted 60 lines · Boris Brezillon
Archit, Laurent,
Quoted 42 lines · On Tue, 28 Jul 2015 13:47:37 +0530 Archit Taneja <[email protected]> wrote:
Hi,
Quoted 7 lines · Laurent Pinchart
Hi Archit,
(CC'ing Boris Brezillon)
Thank you for the patch.
On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
Quoted 8 lines
Quoted 3 lines
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
i2c slave encoders and bridges aren't exactly the same. slave encoders are used when the there is no real 'encoder' in the display chain. bridges are used when there is already an encoder available, and the bridge entity represents another encoder in the chain.
ADV7511 takes in RGB/MIPI DPI data, which is generally the output of a crtc for drm drivers.
ADV7533 takes in MIPI DSI data, which is generally the output of an encoder for drm drivers.
Therefore, having i2c slave encoder for the former and bridge for the latter made sense to me.
I do agree that it would be better if they were somehow merged. It would prevent the fragmentation we currently have among encoder chips.
One possible way would be to convert slave encoder to bridge. With this, an i2c slave encoder would be a 'dummy encoder' and a bridge. i2c slave encoders even now just tie the slave encoder helper funcs to encoder helper funcs. So it's not really any different.
Quoted 6 lines
Merging these 2 entities would be nice, but we're still shying away from the larger problem of creating generic encoder chains. The ideal solution would be for bridges and slave encoders to just be 'encoders', and the facility to connect on encoder output to the input of another. I don't know how easy it is to do this, and whether it'll break userspace.
Yes, that's pretty much what I was trying to do.
I'd also like to ease display pipelines creation by providing helper functions, so that display controller don't have to worry about encoders and connectors creation if these ones are attached to external encoders.Quoted 1 line
Quoted 8 lines
Quoted 5 lines
Archit
Quoted 3 lines
Boris, I know you were experimenting with that, do you have anything to report ?
Nope, I didn't work on it since last time we talked about it. I pushed my work here if you want to have a look [1].
I went through the branch you shared. From what I understood, the encoder chain comprises of one 'real' encoder object (
drm_encoder) in the 'drm_encoder_chain' struct. Thisdrm_encoderencapsulates all the 'encoder elements' forming the chain.I'm guessing the various dridge/slave encoder drivers would have to be changed to now create a
drm_encoder_elementobject, replacing drm_bridge/drm_i2c_slave_encoder objects.
Quoted 5 lines
One problem I see with this approach is that we can't use this when the display controller already exposes a
drm_encoder. I.e, it already creates adrm_encoderobject. If we want the encoder chain to be connected to the output of this encoder, we'll need to link the 2drm_encoderstogether, which isn't possible at the moment.
Actually my goal was to move everybody to the drm_encoder_element model, even the encoder directly provided by the display controller IP. If the internal encoder is actually directly connected to a connector, then the encoder chain will just contain one element, but everything should work fine.
Quoted 8 lines
I guess we have two ways to go about this:
1) Have an approach like this where all the entities in the encoder chain connect to just one encoder. We define the sequence in which they are connected. The drm kms framework acts as if this chain doesn't exist, and assumes that this is what the encoder is outputting.
Yep, that's pretty much what I've done. The main reason for doing that is to keep the interface with the userspace unchanged.
Quoted 5 lines
2) Make each element in the chain be a '
drm_encoder' object in itself. This would be a more intrusive change, sincedrm_encodersare expected to receive an input from crtc, and output to a connector. Furthermore, it may confuse userspace what encoder to chose.
That's why Laurent suggested to go for the 1st approach.
Quoted 7 lines
For 1), we could either work more on your approach, or use
drm_bridges.drm_bridgescan already be chained to each other, and bridge ops of each bridge in the chain are called successively. It still relies on the device drivers to form the chain, which is something your approach takes care of by itself. But that's something that can be extended for bridges too.
Can we really chain several bridges ?
Also note that I plan to automate the encoder chain creation, or at least provide helper functions so that in standard cases the display controller does not have to bother creating its encoder chain. This is particularly true for platforms supporting DT, the encoder chain + connector can be declared in a generic way, and the core could provide helper functions to parse and create the encoder chain and the endpoint connector.
Quoted 7 lines
Laurent,
Merging i2c slave encoders and bridges is possible, but there is no guarantee that the new solution would be future proof and work well with encoder chains. We needed more consensus from folks on dri-devel.
I'll let Laurent correct me if I'm wrong, but I think the plan was to move all slave encoders and bridges to the encoder element representation.
Best Regards,
Boris
Signature · 7 lines
Boris Brezillon, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Quoted 92 lines · Boris Brezillon
Hi Archit,
Quoted 81 lines · On Fri, 31 Jul 2015 10:56:20 +0530 Archit Taneja <[email protected]> wrote:
Hi Boris, Laurent,
Quoted 60 lines · Boris Brezillon
Archit, Laurent,
Quoted 42 lines · On Tue, 28 Jul 2015 13:47:37 +0530 Archit Taneja <[email protected]> wrote:
Hi,
Quoted 7 lines · Laurent Pinchart
Hi Archit,
(CC'ing Boris Brezillon)
Thank you for the patch.
On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
Quoted 8 lines
Quoted 3 lines
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
i2c slave encoders and bridges aren't exactly the same. slave encoders are used when the there is no real 'encoder' in the display chain. bridges are used when there is already an encoder available, and the bridge entity represents another encoder in the chain.
ADV7511 takes in RGB/MIPI DPI data, which is generally the output of a crtc for drm drivers.
ADV7533 takes in MIPI DSI data, which is generally the output of an encoder for drm drivers.
Therefore, having i2c slave encoder for the former and bridge for the latter made sense to me.
I do agree that it would be better if they were somehow merged. It would prevent the fragmentation we currently have among encoder chips.
One possible way would be to convert slave encoder to bridge. With this, an i2c slave encoder would be a 'dummy encoder' and a bridge. i2c slave encoders even now just tie the slave encoder helper funcs to encoder helper funcs. So it's not really any different.
Quoted 6 lines
Merging these 2 entities would be nice, but we're still shying away from the larger problem of creating generic encoder chains. The ideal solution would be for bridges and slave encoders to just be 'encoders', and the facility to connect on encoder output to the input of another. I don't know how easy it is to do this, and whether it'll break userspace.
Yes, that's pretty much what I was trying to do.
I'd also like to ease display pipelines creation by providing helper functions, so that display controller don't have to worry about encoders and connectors creation if these ones are attached to external encoders.Quoted 1 line
Quoted 8 lines
Quoted 5 lines
Archit
Quoted 3 lines
Boris, I know you were experimenting with that, do you have anything to report ?
Nope, I didn't work on it since last time we talked about it. I pushed my work here if you want to have a look [1].
I went through the branch you shared. From what I understood, the encoder chain comprises of one 'real' encoder object (
drm_encoder) in the 'drm_encoder_chain' struct. Thisdrm_encoderencapsulates all the 'encoder elements' forming the chain.I'm guessing the various dridge/slave encoder drivers would have to be changed to now create a
drm_encoder_elementobject, replacing drm_bridge/drm_i2c_slave_encoder objects.Quoted 5 lines
One problem I see with this approach is that we can't use this when the display controller already exposes a
drm_encoder. I.e, it already creates adrm_encoderobject. If we want the encoder chain to be connected to the output of this encoder, we'll need to link the 2drm_encoderstogether, which isn't possible at the moment.
Quoted 5 lines
Actually my goal was to move everybody to the
drm_encoder_elementmodel, even the encoder directly provided by the display controller IP. If the internal encoder is actually directly connected to a connector, then the encoder chain will just contain one element, but everything should work fine.
Okay. That approach makes sense.
It might be good to have a look at the current state of drm_bridge. We need to probably make a call between extending bridges or starting with encoder elements from scratch. Extending bridges might be less intrusive. Although, encoder elements is more uniform. In bridges, we'll be stuck with two entities: One encoder (drm_encoder), followed by a chain of bridges.
Quoted 22 lines
Quoted 9 lines
I guess we have two ways to go about this:
1) Have an approach like this where all the entities in the encoder chain connect to just one encoder. We define the sequence in which they are connected. The drm kms framework acts as if this chain doesn't exist, and assumes that this is what the encoder is outputting.
Yep, that's pretty much what I've done. The main reason for doing that is to keep the interface with the userspace unchanged.
Quoted 5 lines
2) Make each element in the chain be a '
drm_encoder' object in itself. This would be a more intrusive change, sincedrm_encodersare expected to receive an input from crtc, and output to a connector. Furthermore, it may confuse userspace what encoder to chose.That's why Laurent suggested to go for the 1st approach.
Quoted 1 line
Quoted 8 lines
Quoted 6 lines
For 1), we could either work more on your approach, or use
drm_bridges.drm_bridgescan already be chained to each other, and bridge ops of each bridge in the chain are called successively. It still relies on the device drivers to form the chain, which is something your approach takes care of by itself. But that's something that can be extended for bridges too.Can we really chain several bridges ?
Yes. The support was recently added. We can link one bridge to another via drm_bridge_attach(), by populating the bridge->next field.
The bridge helpers used in atomic_helper.c and crtc_helper.c recursively call all the bridges in the chain.
Quoted 8 lines
Also note that I plan to automate the encoder chain creation, or at least provide helper functions so that in standard cases the display controller does not have to bother creating its encoder chain. This is particularly true for platforms supporting DT, the encoder chain + connector can be declared in a generic way, and the core could provide helper functions to parse and create the encoder chain and the endpoint connector.
This would be quite useful.
Quoted 4 lines
Quoted 4 lines
Laurent,
Quoted 8 lines
Quoted 4 lines
Merging i2c slave encoders and bridges is possible, but there is no guarantee that the new solution would be future proof and work well with encoder chains. We needed more consensus from folks on dri-devel.
I'll let Laurent correct me if I'm wrong, but I think the plan was to move all slave encoders and bridges to the encoder element representation.
Some troubles I've had when working with encoder chains:
- There can be dependencies between two elements in the chain. For example, an element in the chain might provide interface clocks for the next element in the chain. The laterelement shouldn't even try to touch its registers if the previous element isn't enabled.
- The sequence in which each encoder element needs to be called. Some have to be first to last, others last to first.
- Some external encoder drivers(currently bridge, i2c slaves) create their own connectors within the driver. If such an encoder is placed in the middle of an encoder chain. It could lead to problems.
We might want to consider these (and probably more things) when working on the solution.
Thanks,
Archit
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
In reply to Boris BrezillonQuoted 92 lines · Boris Brezillon
Hi Archit,
Quoted 81 lines · On Fri, 31 Jul 2015 10:56:20 +0530 Archit Taneja <[email protected]> wrote:
Hi Boris, Laurent,
Quoted 60 lines · Boris Brezillon
Archit, Laurent,
Quoted 42 lines · On Tue, 28 Jul 2015 13:47:37 +0530 Archit Taneja <[email protected]> wrote:
Hi,
Quoted 7 lines · Laurent Pinchart
Hi Archit,
(CC'ing Boris Brezillon)
Thank you for the patch.
On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
Quoted 8 lines
Quoted 3 lines
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
i2c slave encoders and bridges aren't exactly the same. slave encoders are used when the there is no real 'encoder' in the display chain. bridges are used when there is already an encoder available, and the bridge entity represents another encoder in the chain.
ADV7511 takes in RGB/MIPI DPI data, which is generally the output of a crtc for drm drivers.
ADV7533 takes in MIPI DSI data, which is generally the output of an encoder for drm drivers.
Therefore, having i2c slave encoder for the former and bridge for the latter made sense to me.
I do agree that it would be better if they were somehow merged. It would prevent the fragmentation we currently have among encoder chips.
One possible way would be to convert slave encoder to bridge. With this, an i2c slave encoder would be a 'dummy encoder' and a bridge. i2c slave encoders even now just tie the slave encoder helper funcs to encoder helper funcs. So it's not really any different.
Quoted 6 lines
Merging these 2 entities would be nice, but we're still shying away from the larger problem of creating generic encoder chains. The ideal solution would be for bridges and slave encoders to just be 'encoders', and the facility to connect on encoder output to the input of another. I don't know how easy it is to do this, and whether it'll break userspace.
Yes, that's pretty much what I was trying to do.
I'd also like to ease display pipelines creation by providing helper functions, so that display controller don't have to worry about encoders and connectors creation if these ones are attached to external encoders.Quoted 1 line
Quoted 8 lines
Quoted 5 lines
Archit
Quoted 3 lines
Boris, I know you were experimenting with that, do you have anything to report ?
Nope, I didn't work on it since last time we talked about it. I pushed my work here if you want to have a look [1].
I went through the branch you shared. From what I understood, the encoder chain comprises of one 'real' encoder object (
drm_encoder) in the 'drm_encoder_chain' struct. Thisdrm_encoderencapsulates all the 'encoder elements' forming the chain.I'm guessing the various dridge/slave encoder drivers would have to be changed to now create a
drm_encoder_elementobject, replacing drm_bridge/drm_i2c_slave_encoder objects.Quoted 5 lines
One problem I see with this approach is that we can't use this when the display controller already exposes a
drm_encoder. I.e, it already creates adrm_encoderobject. If we want the encoder chain to be connected to the output of this encoder, we'll need to link the 2drm_encoderstogether, which isn't possible at the moment.
Quoted 5 lines
Actually my goal was to move everybody to the
drm_encoder_elementmodel, even the encoder directly provided by the display controller IP. If the internal encoder is actually directly connected to a connector, then the encoder chain will just contain one element, but everything should work fine.
so.. I'd be careful about changing the role of drm_encoder, as it does play a small role in the interface exposed to userspace.
If you do anything, I think you need to make i2c-encoder-slave stuff look like a drm_bridge + drm_connector, since bridge is not visible to userspace and can already be chained... which I think ends up making it more like how adv7533 looks w/ archit's patches.
That said, the adv7511 type case (raw parallel output) is kind of a better fit for the existing i2c-slave-encoder model, vs adv7533 where you already have a dsi encoder and is a better fit for the drm_bridge model. So maybe there is still a place for both.
At any rate, if we do unify, I think we should go towards the drm_bridge + drm_connector approach and migrate i2c-encoder users over to that. Which would make Archit's approach a reasonable transition step. We just drop the i2c-encoder part of it when none of the adv7511 users still depend on that.
BR,
-R
Quoted 54 lines
Quoted 8 lines
I guess we have two ways to go about this:
1) Have an approach like this where all the entities in the encoder chain connect to just one encoder. We define the sequence in which they are connected. The drm kms framework acts as if this chain doesn't exist, and assumes that this is what the encoder is outputting.
Yep, that's pretty much what I've done. The main reason for doing that is to keep the interface with the userspace unchanged.
Quoted 5 lines
2) Make each element in the chain be a '
drm_encoder' object in itself. This would be a more intrusive change, sincedrm_encodersare expected to receive an input from crtc, and output to a connector. Furthermore, it may confuse userspace what encoder to chose.That's why Laurent suggested to go for the 1st approach.
Quoted 7 lines
For 1), we could either work more on your approach, or use
drm_bridges.drm_bridgescan already be chained to each other, and bridge ops of each bridge in the chain are called successively. It still relies on the device drivers to form the chain, which is something your approach takes care of by itself. But that's something that can be extended for bridges too.Can we really chain several bridges ?
Also note that I plan to automate the encoder chain creation, or at least provide helper functions so that in standard cases the display controller does not have to bother creating its encoder chain. This is particularly true for platforms supporting DT, the encoder chain + connector can be declared in a generic way, and the core could provide helper functions to parse and create the encoder chain and the endpoint connector.
Quoted 7 lines
Laurent,
Merging i2c slave encoders and bridges is possible, but there is no guarantee that the new solution would be future proof and work well with encoder chains. We needed more consensus from folks on dri-devel.
I'll let Laurent correct me if I'm wrong, but I think the plan was to move all slave encoders and bridges to the encoder element representation.
Best Regards,
Boris
Quoted 8 lines
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Hi Rob,
Quoted 16 lines · On Fri, 31 Jul 2015 08:13:59 -0400 Rob Clark <[email protected]> wrote:
Quoted 16 lines
Quoted 15 lines
I went through the branch you shared. From what I understood, the encoder chain comprises of one 'real' encoder object (
drm_encoder) in the 'drm_encoder_chain' struct. Thisdrm_encoderencapsulates all the 'encoder elements' forming the chain.I'm guessing the various dridge/slave encoder drivers would have to be changed to now create a
drm_encoder_elementobject, replacing drm_bridge/drm_i2c_slave_encoder objects.One problem I see with this approach is that we can't use this when the display controller already exposes a
drm_encoder. I.e, it already creates adrm_encoderobject. If we want the encoder chain to be connected to the output of this encoder, we'll need to link the 2drm_encoderstogether, which isn't possible at the moment.
Quoted 8 lines
Quoted 5 lines
Actually my goal was to move everybody to the
drm_encoder_elementmodel, even the encoder directly provided by the display controller IP. If the internal encoder is actually directly connected to a connector, then the encoder chain will just contain one element, but everything should work fine.so.. I'd be careful about changing the role of
drm_encoder, as it does play a small role in the interface exposed to userspace.
I don't think I changed the role of the drm_encoder in my approach. Actually I'm only exposing one encoder for the whole encoder chain. The encoder chain is containing one or several encoder elements, which are not exposed to userspace.
Quoted 5 lines
If you do anything, I think you need to make i2c-encoder-slave stuff look like a
drm_bridge+drm_connector, since bridge is not visible to userspace and can already be chained... which I think ends up making it more like how adv7533 looks w/ archit's patches.
Okay, maybe we can do the same with drm bridges (I wasn't aware that these ones could be chained before Archit mentioned it).
I remember that I was missing a few features in the DRM bridge implementation (like the possibility to negotiate the format passed on the link between 2 encoders), but that's probably something we can add.
Quoted 5 lines
That said, the adv7511 type case (raw parallel output) is kind of a better fit for the existing i2c-slave-encoder model, vs adv7533 where you already have a dsi encoder and is a better fit for the
drm_bridgemodel. So maybe there is still a place for both.
Excuse my ignorance, but I still don't get why the RGB/MIPI DPI are not represented as encoders. They are dummy encoders which just forwards the output of the display controller in raw RGB format, but still. IMHO, representing them as encoders in the chain would ease the whole thing.
Moreover, by doing that we would be able to link this RGB/DPI encoder to a bridge, and we wouldn't have to differentiate the encoder-slave and bridge elements.
Quoted 6 lines
At any rate, if we do unify, I think we should go towards the
drm_bridge+drm_connectorapproach and migrate i2c-encoder users over to that. Which would make Archit's approach a reasonable transition step. We just drop the i2c-encoder part of it when none of the adv7511 users still depend on that.
Another problem I've seen with some drm bridge drivers is that they directly create their own connector, which, as Archit stated, is wrong if you decide to chain this bridge with another bridge. The other reason why the bridge should not create the connector by its own is that in some case the encoder supports different types of connectors (a TDMS encoder can be used to output HDMI or DVI), and thus, selecting the connector type should be left to the part responsible for creating the display pipelines.
This being said, I'm definitely not an expert in this area, so don't hesitate to show me where I'm wrong.
Best Regards,
Boris
Signature · 3 lines
Boris Brezillon, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Quoted 41 lines · Boris Brezillon
Hi Rob,
Quoted 16 lines · On Fri, 31 Jul 2015 08:13:59 -0400 Rob Clark <[email protected]> wrote:
Quoted 16 lines
Quoted 15 lines
I went through the branch you shared. From what I understood, the encoder chain comprises of one 'real' encoder object (
drm_encoder) in the 'drm_encoder_chain' struct. Thisdrm_encoderencapsulates all the 'encoder elements' forming the chain.I'm guessing the various dridge/slave encoder drivers would have to be changed to now create a
drm_encoder_elementobject, replacing drm_bridge/drm_i2c_slave_encoder objects.One problem I see with this approach is that we can't use this when the display controller already exposes a
drm_encoder. I.e, it already creates adrm_encoderobject. If we want the encoder chain to be connected to the output of this encoder, we'll need to link the 2drm_encoderstogether, which isn't possible at the moment.Quoted 8 lines
Quoted 5 lines
Actually my goal was to move everybody to the
drm_encoder_elementmodel, even the encoder directly provided by the display controller IP. If the internal encoder is actually directly connected to a connector, then the encoder chain will just contain one element, but everything should work fine.so.. I'd be careful about changing the role of
drm_encoder, as it does play a small role in the interface exposed to userspace.I don't think I changed the role of the
drm_encoderin my approach. Actually I'm only exposing one encoder for the whole encoder chain. The encoder chain is containing one or several encoder elements, which are not exposed to userspace.Quoted 5 lines
If you do anything, I think you need to make i2c-encoder-slave stuff look like a
drm_bridge+drm_connector, since bridge is not visible to userspace and can already be chained... which I think ends up making it more like how adv7533 looks w/ archit's patches.
Quoted 5 lines
Okay, maybe we can do the same with drm bridges (I wasn't aware that these ones could be chained before Archit mentioned it).
I remember that I was missing a few features in the DRM bridge implementation (like the possibility to negotiate the format passed on the link between 2 encoders), but that's probably something we can add.
chaining bridges is very recent addition, fwiw
At any rate, extending bridge where needed seems preferable over adding new types of objects, I think.
Quoted 11 lines
Quoted 5 lines
That said, the adv7511 type case (raw parallel output) is kind of a better fit for the existing i2c-slave-encoder model, vs adv7533 where you already have a dsi encoder and is a better fit for the
drm_bridgemodel. So maybe there is still a place for both.Excuse my ignorance, but I still don't get why the RGB/MIPI DPI are not represented as encoders. They are dummy encoders which just forwards the output of the display controller in raw RGB format, but still. IMHO, representing them as encoders in the chain would ease the whole thing.
Yeah, creating a dummy encoder in the driver would be the approach to switch from i2c-encoder to bridge. I didn't mean to imply that this couldn't be done. The only point I was trying to make was that for simple cases don't need this currently. (The case I'm more familiar w/ is tilcdc -> tda998x but I guess other simple display controllers to adv7511 is probably similar)
I guess in the i2c-encoder case the driver ends up creating a sort of shim encoder/connector, so maybe it isn't that much different. It is a bunch of shuffling things around to change from i2c-encoder to bridge, and it ends up effecting a bunch of drivers (including some less simple ones like nouveau), so I'm not sure the best migration path. Exposing both i2c-encoder and bridge interfaces for a period of time seems unavoidable..
Quoted 11 lines
Moreover, by doing that we would be able to link this RGB/DPI encoder to a bridge, and we wouldn't have to differentiate the encoder-slave and bridge elements.
Quoted 6 lines
At any rate, if we do unify, I think we should go towards the
drm_bridge+drm_connectorapproach and migrate i2c-encoder users over to that. Which would make Archit's approach a reasonable transition step. We just drop the i2c-encoder part of it when none of the adv7511 users still depend on that.
Quoted 3 lines
Another problem I've seen with some drm bridge drivers is that they directly create their own connector, which, as Archit stated, is wrong if you decide to chain this bridge with another bridge. The other
I agree with Archit on this. He took this approach w/ msm support for external bridges, and it seems sensible that the last bridge constructs the connector. (Plus presumably that is where hpd, ddc probing, etc, is happing)
Quoted 5 lines
reason why the bridge should not create the connector by its own is that in some case the encoder supports different types of connectors (a TDMS encoder can be used to output HDMI or DVI), and thus, selecting the connector type should be left to the part responsible for creating the display pipelines.
did you mean "should" instead of "should not"? Otherwise I don't think I understand..
BR,
-R
Quoted 11 lines
This being said, I'm definitely not an expert in this area, so don't hesitate to show me where I'm wrong.
Best Regards,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Hi,
Quoted 7 lines · Rob Clark
Quoted 5 lines · Boris Brezillon
Hi Rob,
On Fri, 31 Jul 2015 08:13:59 -0400
Rob Clark <[email protected]> wrote:
(...)
Quoted 9 lines
Quoted 4 lines
Another problem I've seen with some drm bridge drivers is that they directly create their own connector, which, as Archit stated, is wrong if you decide to chain this bridge with another bridge. The other
I agree with Archit on this. He took this approach w/ msm support for external bridges, and it seems sensible that the last bridge constructs the connector. (Plus presumably that is where hpd, ddc probing, etc, is happing)
With this approach many bridges should construct connector conditionally, depending if there is something behind them in pipeline (the same is true for encoders and even crtcs). It works, but for me there is lot of unnecessary code and all those conditional paths make things less friendly for development. Wouldn't be better to move creation of the connector to the main drm driver, it would require probably adding some opses/fields to drm_bridges but the drivers would be simpler, I guess.
Regards
Andrzej
Quoted 7 lines
Quoted 6 lines
reason why the bridge should not create the connector by its own is that in some case the encoder supports different types of connectors (a TDMS encoder can be used to output HDMI or DVI), and thus, selecting the connector type should be left to the part responsible for creating the display pipelines.
Quoted 17 lines
did you mean "should" instead of "should not"? Otherwise I don't think I understand..
BR,
-RQuoted 11 lines
This being said, I'm definitely not an expert in this area, so don't hesitate to show me where I'm wrong.
Best Regards,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Quoted 23 lines · Andrzej Hajda
Hi,
Quoted 7 lines · Rob Clark
Quoted 5 lines · Boris Brezillon
Hi Rob,
On Fri, 31 Jul 2015 08:13:59 -0400
Rob Clark <[email protected]> wrote:(...)
Quoted 9 lines
Quoted 4 lines
Another problem I've seen with some drm bridge drivers is that they directly create their own connector, which, as Archit stated, is wrong if you decide to chain this bridge with another bridge. The other
I agree with Archit on this. He took this approach w/ msm support for external bridges, and it seems sensible that the last bridge constructs the connector. (Plus presumably that is where hpd, ddc probing, etc, is happing)
Quoted 7 lines
With this approach many bridges should construct connector conditionally, depending if there is something behind them in pipeline (the same is true for encoders and even crtcs). It works, but for me there is lot of unnecessary code and all those conditional paths make things less friendly for development. Wouldn't be better to move creation of the connector to the main drm driver, it would require probably adding some opses/fields to
drm_bridgesbut the drivers would be simpler, I guess.
six of one, half dozen of the other.. you'd still need to implement
the hpd and ddc probe bits, and that sort of thing *somewhere*. Whether it is directly by implementing drm_connector in the bridge, or indirectly via some extra drm_bridge op's called by a shim connector in the main drm driver, doesn't really seem to change things..
BR,
-R
Quoted 29 lines
Regards
AndrzejQuoted 24 lines
Quoted 6 lines
reason why the bridge should not create the connector by its own is that in some case the encoder supports different types of connectors (a TDMS encoder can be used to output HDMI or DVI), and thus, selecting the connector type should be left to the part responsible for creating the display pipelines.
did you mean "should" instead of "should not"? Otherwise I don't think I understand..
BR,
-RQuoted 11 lines
This being said, I'm definitely not an expert in this area, so don't hesitate to show me where I'm wrong.
Best Regards,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Quoted 27 lines · Rob Clark
Quoted 19 lines · Andrzej Hajda
Hi,
Quoted 7 lines · Rob Clark
Quoted 5 lines · Boris Brezillon
Hi Rob,
On Fri, 31 Jul 2015 08:13:59 -0400
Rob Clark <[email protected]> wrote:(...)
Quoted 7 lines
Quoted 3 lines
Another problem I've seen with some drm bridge drivers is that they directly create their own connector, which, as Archit stated, is wrong if you decide to chain this bridge with another bridge. The other
I agree with Archit on this. He took this approach w/ msm support for external bridges, and it seems sensible that the last bridge constructs the connector. (Plus presumably that is where hpd, ddc probing, etc, is happing)
Quoted 7 lines
With this approach many bridges should construct connector conditionally, depending if there is something behind them in pipeline (the same is true for encoders and even crtcs). It works, but for me there is lot of unnecessary code and all those conditional paths make things less friendly for development. Wouldn't be better to move creation of the connector to the main drm driver, it would require probably adding some opses/fields to
drm_bridgesbut the drivers would be simpler, I guess.
Quoted 5 lines
six of one, half dozen of the other.. you'd still need to implement
the hpd and ddc probe bits, and that sort of thing *somewhere*. Whether it is directly by implementingdrm_connectorin the bridge, or indirectly via some extradrm_bridgeop's called by a shim connector in the main drm driver, doesn't really seem to change things..
The difference is that instead of duplicating connector related code in every driver you will call one helper from the main drm driver/core.
Regards
Andrzej
Quoted 29 lines
BR,
-RQuoted 25 lines
Regards
AndrzejQuoted 22 lines
Quoted 5 lines
reason why the bridge should not create the connector by its own is that in some case the encoder supports different types of connectors (a TDMS encoder can be used to output HDMI or DVI), and thus, selecting the connector type should be left to the part responsible for creating the display pipelines.
did you mean "should" instead of "should not"? Otherwise I don't think I understand..
BR,
-RQuoted 11 lines
This being said, I'm definitely not an expert in this area, so don't hesitate to show me where I'm wrong.
Best Regards,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Quoted 28 lines · Andrzej Hajda
Quoted 27 lines · Rob Clark
Quoted 26 lines · Andrzej Hajda
Hi,
Quoted 7 lines · Rob Clark
Quoted 5 lines · Boris Brezillon
Hi Rob,
On Fri, 31 Jul 2015 08:13:59 -0400
Rob Clark <[email protected]> wrote:(...)
Quoted 7 lines
Quoted 3 lines
Another problem I've seen with some drm bridge drivers is that they directly create their own connector, which, as Archit stated, is wrong if you decide to chain this bridge with another bridge. The other
I agree with Archit on this. He took this approach w/ msm support for external bridges, and it seems sensible that the last bridge constructs the connector. (Plus presumably that is where hpd, ddc probing, etc, is happing)
With this approach many bridges should construct connector conditionally, depending if there is something behind them in pipeline (the same is true for encoders and even crtcs). It works, but for me there is lot of unnecessary code and all those conditional paths make things less friendly for development. Wouldn't be better to move creation of the connector to the main drm driver, it would require probably adding some opses/fields to
drm_bridgesbut the drivers would be simpler, I guess.
Quoted 8 lines
Quoted 5 lines
six of one, half dozen of the other.. you'd still need to implement
the hpd and ddc probe bits, and that sort of thing *somewhere*. Whether it is directly by implementingdrm_connectorin the bridge, or indirectly via some extradrm_bridgeop's called by a shim connector in the main drm driver, doesn't really seem to change things..The difference is that instead of duplicating connector related code in every driver you will call one helper from the main drm driver/core.
Which isn't more than a few lines of code.. I mean, looking at a couple connectors, the bulk of the code is hpd and ddc related. That doesn't magically go away. There isn't that many lines of boilerplate, so meh.
BR,
-R
Quoted 33 lines
Regards
AndrzejQuoted 29 lines
BR,
-RQuoted 25 lines
Regards
AndrzejQuoted 22 lines
Quoted 5 lines
reason why the bridge should not create the connector by its own is that in some case the encoder supports different types of connectors (a TDMS encoder can be used to output HDMI or DVI), and thus, selecting the connector type should be left to the part responsible for creating the display pipelines.
did you mean "should" instead of "should not"? Otherwise I don't think I understand..
BR,
-RQuoted 11 lines
This being said, I'm definitely not an expert in this area, so don't hesitate to show me where I'm wrong.
Best Regards,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Quoted 35 lines · Rob Clark
Quoted 34 lines · Andrzej Hajda
Quoted 32 lines · Rob Clark
Quoted 19 lines · Andrzej Hajda
Hi,
Quoted 7 lines · Rob Clark
Quoted 5 lines · Boris Brezillon
Hi Rob,
On Fri, 31 Jul 2015 08:13:59 -0400
Rob Clark <[email protected]> wrote:(...)
Quoted 7 lines
Quoted 3 lines
Another problem I've seen with some drm bridge drivers is that they directly create their own connector, which, as Archit stated, is wrong if you decide to chain this bridge with another bridge. The other
I agree with Archit on this. He took this approach w/ msm support for external bridges, and it seems sensible that the last bridge constructs the connector. (Plus presumably that is where hpd, ddc probing, etc, is happing)
Quoted 7 lines
With this approach many bridges should construct connector conditionally, depending if there is something behind them in pipeline (the same is true for encoders and even crtcs). It works, but for me there is lot of unnecessary code and all those conditional paths make things less friendly for development. Wouldn't be better to move creation of the connector to the main drm driver, it would require probably adding some opses/fields to
drm_bridgesbut the drivers would be simpler, I guess.six of one, half dozen of the other.. you'd still need to implement
the hpd and ddc probe bits, and that sort of thing *somewhere*. Whether it is directly by implementingdrm_connectorin the bridge, or indirectly via some extradrm_bridgeop's called by a shim connector in the main drm driver, doesn't really seem to change things..
Quoted 7 lines
Quoted 2 lines
The difference is that instead of duplicating connector related code in every driver you will call one helper from the main drm driver/core.
Which isn't more than a few lines of code.. I mean, looking at a couple connectors, the bulk of the code is hpd and ddc related. That doesn't magically go away. There isn't that many lines of boilerplate, so meh.
Could we get to a consensus for this?
Is it okay for bridge and i2c_encoder to co-exist for now?
Thanks,
Archit
Quoted 37 lines
BR,
-RQuoted 33 lines
Regards
AndrzejQuoted 29 lines
BR,
-RQuoted 25 lines
Regards
AndrzejQuoted 22 lines
Quoted 5 lines
reason why the bridge should not create the connector by its own is that in some case the encoder supports different types of connectors (a TDMS encoder can be used to output HDMI or DVI), and thus, selecting the connector type should be left to the part responsible for creating the display pipelines.
did you mean "should" instead of "should not"? Otherwise I don't think I understand..
BR,
-RQuoted 11 lines
This being said, I'm definitely not an expert in this area, so don't hesitate to show me where I'm wrong.
Best Regards,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
In reply to Laurent PinchartQuoted 7 lines · Laurent Pinchart
Hi Archit,
(CC'ing Boris Brezillon)
Thank you for the patch.
On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
Quoted 8 lines
Quoted 3 lines
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
btw, what is the status here? I'd kind of lost track of the discussion, but I'm getting impatient that it is somehow taking ridiculously long to get adv7533 support merged. (It's good thing the x86/desktop folks don't bikeshed so much.. I'd hate to wait a year for my new laptop to be supported..)
Anyways, if needed, just copy/paste the adv7511/7533 code into a separate bridge-only driver, and we'll use that. Once the i2c-slave-encoder users for adv7511 are converted over, we can delete the original slave encoder driver. That seems like a sane transition plan to a bridge-only world.
BR,
-R
Quoted 159 lines
Boris, I know you were experimenting with that, do you have anything to report ?
Quoted 142 lines
Move the code in encoder slave functions to generate helpers that are agnostic to the drm object type. These helpers will later also be used by bridge and connecter helper functions.
Signed-off-by Archit Taneja <[email protected]>--- drivers/gpu/drm/i2c/adv7511.c | 80 +++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 23 deletions(-)drivers/gpu/drm/i2c/adv7511.c +55
-25@@ -612,13 +612,11 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, }/* --------------------------------------------------------------------------- -- - * Encoder operations +* ADV75xx helpers */ - -static int adv7511_get_modes (struct drm_encoder *encoder, -struct drm_connector *connector) +static int adv7511_get_modes (struct adv7511 *adv7511, +struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);struct edid *edid;unsigned int count;@@ -656,21 +654,10 @@ static int adv7511_get_modes(struct drm_encoder *encoder, return count; } -static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) -{ -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); - -if (mode ==DRM_MODE_DPMS_ON ) -adv7511_power_on (adv7511); -else -adv7511_power_off (adv7511); -} -static enum drm_connector_status -adv7511_encoder_detect (struct drm_encoder *encoder, +adv7511_detect (struct adv7511 *adv7511,struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);enum drm_connector_status status;unsigned int val;bool hpd;@@ -694,7 +681,7 @@ adv7511_encoder_detect(struct drm_encoder *encoder,if (status == connector_status_connected && hpd && adv7511->powered) {regcache_mark_dirty (adv7511->regmap);adv7511_power_on (adv7511); -adv7511_get_modes (encoder, connector); +adv7511_get_modes (adv7511, connector);if (adv7511->status == connector_status_connected) status = connector_status_disconnected; }else {@@ -708,8 +695,8 @@ adv7511_encoder_detect(struct drm_encoder *encoder,return status; } -static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, -struct drm_display_mode *mode) +static int adv7511_mode_valid (struct adv7511 *adv7511, +const struct drm_display_mode *mode) {if (mode->clock >165000 )return MODE_CLOCK_HIGH ;@@ -717,11 +704,10 @@ static int adv7511_encoder_mode_valid(struct drm_encoder *encoder, return MODE_OK; } -static void adv7511_encoder_mode_set (struct drm_encoder *encoder, +static void adv7511_mode_set (struct adv7511 *adv7511,struct drm_display_mode *mode,struct drm_display_mode *adj_mode) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);unsigned int low_refresh_rate;unsigned int hsync_polarity =0 ;unsigned int vsync_polarity =0 ;@@ -812,12 +798,60 @@ static void adv7511_encoder_mode_set(struct drm_encoder *encoder, adv7511->f_tmds = mode->clock; } +/* --------------------------------------------------------------------------- -- + * Encoder operations +*/ + +static int adv7511_encoder_get_modes (struct drm_encoder *encoder, +struct drm_connector *connector) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_get_modes (adv7511, connector); +} + +static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +if (mode ==DRM_MODE_DPMS_ON ) +adv7511_power_on (adv7511); +else +adv7511_power_off (adv7511); +} + +static enum drm_connector_status +adv7511_encoder_detect (struct drm_encoder *encoder, +struct drm_connector *connector) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_detect (adv7511, connector); +} + +static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, +struct drm_display_mode *mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_mode_valid (adv7511, mode); +} + +static void adv7511_encoder_mode_set (struct drm_encoder *encoder, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +adv7511_mode_set (adv7511, mode, adj_mode); +} +static struct drm_encoder_slave_funcs adv7511_encoder_funcs = { .dpms = adv7511_encoder_dpms,drivers/gpu/drm/i2c/adv7511.c static void adv7511_encoder_mode_set(struct
Quoted 10 lines
drivers/gpu/drm/i2c/adv7511.c +1
-3.mode_valid = adv7511_encoder_mode_valid, .mode_set = adv7511_encoder_mode_set, .detect = adv7511_encoder_detect, - .get_modes = adv7511_get_modes, + .get_modes = adv7511_encoder_get_modes, };/* --------------------------------------------------------------------------- -- --
Regards,
Quoted 6 lines
Laurent Pinchart
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Laurent Pinchart
reviewerRe: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Quoted 11 lines · On Thursday 03 December 2015 10:02:02 Rob Clark wrote:
Quoted 9 lines · Laurent Pinchart
Quoted 3 lines · On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
Quoted 5 lines
btw, what is the status here? I'd kind of lost track of the discussion, but I'm getting impatient that it is somehow taking ridiculously long to get adv7533 support merged. (It's good thing the x86/desktop folks don't bikeshed so much.. I'd hate to wait a year for my new laptop to be supported..)
I'd hardly call the overall architecture on which drivers rely a bikeshed (and maybe if x86/desktop folks cared more about embedded there would be more willingness to make the framework evolve in an embedded-friendly way).
Quoted 5 lines
Anyways, if needed, just copy/paste the adv7511/7533 code into a separate bridge-only driver, and we'll use that. Once the i2c-slave-encoder users for adv7511 are converted over, we can delete the original slave encoder driver. That seems like a sane transition plan to a bridge-only world.
It's a very sane way to make sure nobody will do the work and keep two copies of the same code for a long time, yes.
The path forward is pretty clear, the issue is to find someone who can do the work.
Signature · 3 lines
Regards, Laurent Pinchart
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Quoted 18 lines · Laurent Pinchart
Quoted 11 lines · On Thursday 03 December 2015 10:02:02 Rob Clark wrote:
Quoted 9 lines · Laurent Pinchart
Quoted 3 lines · On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
Quoted 5 lines
btw, what is the status here? I'd kind of lost track of the discussion, but I'm getting impatient that it is somehow taking ridiculously long to get adv7533 support merged. (It's good thing the x86/desktop folks don't bikeshed so much.. I'd hate to wait a year for my new laptop to be supported..)
Quoted 3 lines
I'd hardly call the overall architecture on which drivers rely a bikeshed (and maybe if x86/desktop folks cared more about embedded there would be more willingness to make the framework evolve in an embedded-friendly way).
I don't know that we can blame this on the desktop folks like that.. after all i2c-slave was sufficient for embedded devices for some time, and it was an improvement over what came before when it comes to sharing external encoder support (ie. nothing)
But, as was the case with atomic, the framework evolves. And as atomic roll-out has shown, it doesn't require a flag-day if you accept some duplication.
Quoted 8 lines
Quoted 5 lines
Anyways, if needed, just copy/paste the adv7511/7533 code into a separate bridge-only driver, and we'll use that. Once the i2c-slave-encoder users for adv7511 are converted over, we can delete the original slave encoder driver. That seems like a sane transition plan to a bridge-only world.
It's a very sane way to make sure nobody will do the work and keep two copies of the same code for a long time, yes.
As opposed to a change everything at once approach, and corresponding updates to drivers for hw you don't have. That sounds like a *much* saner plan</sarcasm>
Seriously, the cost of duplicating a bit of code is low. Especially when the code you are duplicating is low churn. Duplicating lets other drivers that use adv75xx via slave-encoder migrate over at their own pace. Similar to how atomic was rolled out. To me that sounds like the much more practical way forward.
Quoted 2 lines
The path forward is pretty clear, the issue is to find someone who can do the work.
Maybe the end goal is clear. But apparently the path forward less so.
BR,
-R
Quoted 5 lines
--
Regards,Laurent Pinchart
Laurent Pinchart
reviewerRe: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Hi Rob,
Quoted 19 lines · On Thursday 03 December 2015 10:55:12 Rob Clark wrote:
Quoted 18 lines · Laurent Pinchart
Quoted 16 lines · On Thursday 03 December 2015 10:02:02 Rob Clark wrote:
Quoted 9 lines · Laurent Pinchart
Quoted 3 lines · On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
btw, what is the status here? I'd kind of lost track of the discussion, but I'm getting impatient that it is somehow taking ridiculously long to get adv7533 support merged. (It's good thing the x86/desktop folks don't bikeshed so much.. I'd hate to wait a year for my new laptop to be supported..)
Quoted 6 lines
Quoted 4 lines
I'd hardly call the overall architecture on which drivers rely a bikeshed (and maybe if x86/desktop folks cared more about embedded there would be more willingness to make the framework evolve in an embedded-friendly way).
I don't know that we can blame this on the desktop folks like that..
To be clear I'm not blaming anyone here, just pointing out that the grass isn't all green on the other side ;-)
Quoted 14 lines
after all i2c-slave was sufficient for embedded devices for some time, and it was an improvement over what came before when it comes to sharing external encoder support (ie. nothing)
But, as was the case with atomic, the framework evolves. And as atomic roll-out has shown, it doesn't require a flag-day if you accept some duplication.
Quoted 6 lines
Quoted 5 lines
Anyways, if needed, just copy/paste the adv7511/7533 code into a separate bridge-only driver, and we'll use that. Once the i2c-slave-encoder users for adv7511 are converted over, we can delete the original slave encoder driver. That seems like a sane transition plan to a bridge-only world.
Quoted 6 lines
Quoted 2 lines
It's a very sane way to make sure nobody will do the work and keep two copies of the same code for a long time, yes.
As opposed to a change everything at once approach, and corresponding updates to drivers for hw you don't have. That sounds like a *much* saner plan</sarcasm>
There's a single driver using the adv7511 I2C slave encoder, that's the rcar- du driver. I will make sure to update and test the driver.
Quoted 10 lines
Seriously, the cost of duplicating a bit of code is low. Especially when the code you are duplicating is low churn. Duplicating lets other drivers that use adv75xx via slave-encoder migrate over at their own pace. Similar to how atomic was rolled out. To me that sounds like the much more practical way forward.
Quoted 2 lines
The path forward is pretty clear, the issue is to find someone who can do the work.
Maybe the end goal is clear. But apparently the path forward less so.
Signature · 8 lines
Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
In reply to Rob ClarkQuoted 46 lines · Rob Clark
Quoted 18 lines · Laurent Pinchart
Quoted 11 lines · On Thursday 03 December 2015 10:02:02 Rob Clark wrote:
Quoted 9 lines · Laurent Pinchart
Quoted 3 lines · On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Please, no. It's really time to stop piling hacks and fix the problem properly. There's no reason to have separate APIs for I2C slave encoders and DRM bridges. Those two APIs need to be merged, and then you'll find it much easier to implement ADV7533 support.
Quoted 5 lines
btw, what is the status here? I'd kind of lost track of the discussion, but I'm getting impatient that it is somehow taking ridiculously long to get adv7533 support merged. (It's good thing the x86/desktop folks don't bikeshed so much.. I'd hate to wait a year for my new laptop to be supported..)
Quoted 3 lines
I'd hardly call the overall architecture on which drivers rely a bikeshed (and maybe if x86/desktop folks cared more about embedded there would be more willingness to make the framework evolve in an embedded-friendly way).
I don't know that we can blame this on the desktop folks like that.. after all i2c-slave was sufficient for embedded devices for some time, and it was an improvement over what came before when it comes to sharing external encoder support (ie. nothing)
But, as was the case with atomic, the framework evolves. And as atomic roll-out has shown, it doesn't require a flag-day if you accept some duplication.
Quoted 8 lines
Quoted 5 lines
Anyways, if needed, just copy/paste the adv7511/7533 code into a separate bridge-only driver, and we'll use that. Once the i2c-slave-encoder users for adv7511 are converted over, we can delete the original slave encoder driver. That seems like a sane transition plan to a bridge-only world.
It's a very sane way to make sure nobody will do the work and keep two copies of the same code for a long time, yes.
As opposed to a change everything at once approach, and corresponding updates to drivers for hw you don't have. That sounds like a *much* saner plan</sarcasm>
Quoted 8 lines
Seriously, the cost of duplicating a bit of code is low. Especially when the code you are duplicating is low churn. Duplicating lets other drivers that use adv75xx via slave-encoder migrate over at their own pace. Similar to how atomic was rolled out. To me that sounds like the much more practical way forward.
Quoted 2 lines
The path forward is pretty clear, the issue is to find someone who can do the work.
I volunteer (as tribute)!
Once we settle on the best way to do it.
Quoted 2 lines
Maybe the end goal is clear. But apparently the path forward less so.
Laurent, as we'd discussed in the past, I did an initial study of how we could map bridge ops to the encoder slave ops, and change it for the rcar kms driver (and others) that might use adv7511.
The drm_encoder_slave_funcs ops are a superset of bridge ops. The rcar-du driver uses a subset of these ops (encoder-like ops) to implement the hdmi encoder (rcar_du_hdmienc.c) and the other (connector-like ops)for implementing the hdmi connector (rcar_du_hdmicon.c)
We have two options:
1. If we want to use drm_bridge as it is, the rcar driver shouldn't create a hdmi connector anymore, and rely on the adv7511 driver to make a connector for it. This is the easiest way, but it will break the nice representation of the hardware in DT.
2. We add more drm_bridge ops (the ones that implement the connector ops), and make the hdmi connector created by rcar-du use these bridge ops.
Both these options have issues. The 2) one is the probably the better of the two, but I don't know if adding more ops to the bridge is the right way to go.
Therefore, I don't know how we can solve this straight away. If there is more debate needed on this, then it is probably easier to get adv7533 support in, and then figure out how two merge the two.
Archit
Quoted 9 lines
BR,
-RQuoted 5 lines
--
Regards,Laurent Pinchart
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH 3/5] drm/i2c: adv7511: Refactor encoder slave functions
Hi Laurent,
Quoted 13 lines · Archit Taneja
Quoted 10 lines · Rob Clark
Quoted 8 lines · Laurent Pinchart
Quoted 7 lines · On Thursday 03 December 2015 10:02:02 Rob Clark wrote:
Quoted 6 lines · Laurent Pinchart
Quoted 5 lines · On Monday 27 July 2015 11:46:57 Archit Taneja wrote:
ADV7511 is represented as an i2c drm slave encoder device. ADV7533, on
the other hand, is going be a normal i2c client device creating bridge
and connector entities.
<snip>
Quoted 22 lines
Laurent, as we'd discussed in the past, I did an initial study of how we could map bridge ops to the encoder slave ops, and change it for the rcar kms driver (and others) that might use adv7511.
The
drm_encoder_slave_funcsops are a superset of bridge ops. The rcar-du driver uses a subset of these ops (encoder-like ops) to implement the hdmi encoder (rcar_du_hdmienc.c) and the other (connector-like ops)for implementing the hdmi connector (rcar_du_hdmicon.c)We have two options:
1. If we want to use
drm_bridgeas it is, the rcar driver shouldn't create a hdmi connector anymore, and rely on the adv7511 driver to make a connector for it. This is the easiest way, but it will break the nice representation of the hardware in DT.2. We add more
drm_bridgeops (the ones that implement the connector ops), and make the hdmi connector created by rcar-du use these bridge ops.
Quoted 8 lines
Both these options have issues. The 2) one is the probably the better of the two, but I don't know if adding more ops to the bridge is the right way to go.
Therefore, I don't know how we can solve this straight away. If there is more debate needed on this, then it is probably easier to get adv7533 support in, and then figure out how two merge the two.
I gave approach (1) a try. I modified the rcar-du driver to use bridge instead of i2c slave encoder and posted a RFC [1]. The hdmi connector DT nodes (like in r8a7790-lager.dts) aren't really used by the rcar-du driver. Now, with the adv7511 driver creating its own connector, they mean even much less.
The adv7511 refactor from i2c slave encoder to bridge is done in [2].
[1] http://marc.info/?l=dri-devel&m=145235835902378&w=1
[2] http://marc.info/?l=dri-devel&m=145235823602353&w=1
Could you please review and test?
Thanks,
Archit
Quoted 11 lines
Quoted 10 lines
BR,
-RQuoted 5 lines
--
Regards,Laurent Pinchart
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH 4/5 drm/i2c: adv7511: Add drm_bridge/connector for ADV7533
In reply to Archit TanejaCreate bridge and connector helper functions. These internally refer to the ADV75xx helper functions.
The driver registers a drm_bridge object during probe. The bridge, in turn registers a HDMI connector when a user attaches the bridge.
Therefore, when the device type is ADV7533, we create bridge and connector entities, and when it's ADV7511, we create a slave encoder as before.
Since the i2c driver is still wrapped around by the drm_i2c_slave_encoder struct. We make sure the encoder_init op returns an error when the device type is ADV7533.
--- drivers/gpu/drm/i2c/adv7511.c | 155 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+)
drivers/gpu/drm/i2c/adv7511.c +155 -0
@@ -17,6 +17,8 @@#include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> #include <drm/drm_encoder_slave.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include "adv7511.h"
@@ -44,6 +46,9 @@ struct adv7511 {wait_queue_head_t wq;struct drm_encoder *encoder; +struct drm_connector connector; +struct drm_bridge bridge; +bool embedded_sync;enum adv7511_sync_polarity vsync_polarity;enum adv7511_sync_polarity hsync_polarity;
@@ -855,6 +860,139 @@ static struct drm_encoder_slave_funcs adv7511_encoder_funcs = { };/* ----------------------------------------------------------------------------- +* Bridge and connector functions +*/ + +static struct adv7511 *connector_to_adv7511 (struct drm_connector *connector) +{ + return container_of(connector, struct adv7511, connector); +} + +/* Connector helper functions */ +static int adv7533_connector_get_modes (struct drm_connector *connector) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_get_modes (adv, connector); +} + +static struct drm_encoder * +adv7533_connector_best_encoder (struct drm_connector *connector) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv->bridge.encoder; +} + +static enum drm_mode_status +adv7533_connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_mode_valid (adv, mode); +} + +static struct drm_connector_helper_funcs adv7533_connector_helper_funcs = { + .get_modes = adv7533_connector_get_modes, + .best_encoder = adv7533_connector_best_encoder, + .mode_valid = adv7533_connector_mode_valid, +}; + +static enum drm_connector_status +adv7533_connector_detect (struct drm_connector *connector,bool force) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_detect (adv, connector); +} + +static struct drm_connector_funcs adv7533_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = adv7533_connector_detect, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +/* Bridge funcs */ +static struct adv7511 *bridge_to_adv7511 (struct drm_bridge *bridge) +{ + return container_of(bridge, struct adv7511, bridge); +} + +static void adv7533_bridge_pre_enable (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_power_on (adv); +} + +static void adv7533_bridge_post_disable (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_power_off (adv); +} + +static void adv7533_bridge_enable (struct drm_bridge *bridge) +{ +} + +static void adv7533_bridge_disable (struct drm_bridge *bridge) +{ +} + +static void adv7533_bridge_mode_set (struct drm_bridge *bridge, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_mode_set (adv, mode, adj_mode); +} + +static int adv7533_bridge_attach (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); +int ret; + + adv->encoder = bridge->encoder; + +if (!bridge->encoder) { +DRM_ERROR ("Parent encoder object not found" ); +return -ENODEV ; + } + + adv->connector.polled =DRM_CONNECTOR_POLL_HPD ; + ret =drm_connector_init (bridge->dev, &adv->connector, + &adv7533_connector_funcs,DRM_MODE_CONNECTOR_HDMIA ); +if (ret) { +DRM_ERROR ("Failed to initialize connector with drm\n" ); +return ret; + } +drm_connector_helper_add (&adv->connector, + &adv7533_connector_helper_funcs); +drm_connector_register (&adv->connector); +drm_mode_connector_attach_encoder (&adv->connector, adv->encoder); + +drm_helper_hpd_irq_event (adv->connector.dev); + +return ret; +} + +static struct drm_bridge_funcs adv7533_bridge_funcs = { + .pre_enable = adv7533_bridge_pre_enable, + .enable = adv7533_bridge_enable, + .disable = adv7533_bridge_disable, + .post_disable = adv7533_bridge_post_disable, + .mode_set = adv7533_bridge_mode_set, + .attach = adv7533_bridge_attach, +}; + +/* ----------------------------------------------------------------------------- * Probe & remove */
@@ -1079,6 +1217,17 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)if (adv7511->type ==ADV7511 )adv7511_set_link_config (adv7511, &link_config); +if (adv7511->type ==ADV7533 ) { + adv7511->bridge.funcs = &adv7533_bridge_funcs; + adv7511->bridge.of_node = dev->of_node; + + ret =drm_bridge_add (&adv7511->bridge); +if (ret) { +dev_err (dev,"failed to add adv7533 bridge\n" ); + goto err_i2c_unregister_cec; + } + } +return 0 ; err_i2c_unregister_cec:
@@ -1098,6 +1247,9 @@ static int adv7511_remove(struct i2c_client *i2c)kfree (adv7511->edid); +if (adv7511->type ==ADV7533 ) +drm_bridge_remove (&adv7511->bridge); +return 0 ; }
@@ -1107,6 +1259,9 @@ static int adv7511_encoder_init(struct i2c_client *i2c, struct drm_device *dev,struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +if (adv7511->type ==ADV7533 ) +return -ENODEV ; + encoder->slave_priv = adv7511; encoder->slave_funcs = &adv7511_encoder_funcs;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 5/5 drm/i2c: adv7511: Create mipi_dsi_device for ADV7533
In reply to Archit TanejaIn order to pass DSI specific parameters to the DSI host, we need the driver to create a mipi_dsi_device that attaches to the host.
Use of_graph helpers to get the DSI host DT node. Create a dummy dsi device using this host. Finally, attach this device to the host.
Populate few other DT parameters (number of data lanes etc) that are required for DSI RX to work correctly. Hardcode few other parameters (rgb, embedded_sync) for now.
--- drivers/gpu/drm/i2c/adv7511.c | 106 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 7 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +99 -7
@@ -12,6 +12,7 @@#include <linux/module.h> #include <linux/regmap.h> #include <linux/slab.h> +#include <linux/of_graph.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h>
@@ -19,6 +20,7 @@#include <drm/drm_encoder_slave.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_mipi_dsi.h> #include "adv7511.h"
@@ -58,6 +60,11 @@ struct adv7511 {struct gpio_desc *gpio_pd; +/* ADV7533 DSI RX related params */ +struct device_node *host_node; +struct mipi_dsi_device *dsi; +u8 num_dsi_lanes; +enum adv7511_type type; };
@@ -403,8 +410,10 @@ static void adv7511_dsi_receiver_dpms(struct adv7511 *adv7511)return ;if (adv7511->powered) { -/* set number of dsi lanes (hardcoded to 4 for now) */ -regmap_write (adv7511->regmap_cec,0x1c ,0x4 <<4 ); +struct mipi_dsi_device *dsi = adv7511->dsi; + +/* set number of dsi lanes */ +regmap_write (adv7511->regmap_cec,0x1c , dsi->lanes <<4 );/* disable internal timing generator */ regmap_write (adv7511->regmap_cec,0x27 ,0x0b );/* enable hdmi */
@@ -954,6 +963,48 @@ static void adv7533_bridge_mode_set(struct drm_bridge *bridge,adv7511_mode_set (adv, mode, adj_mode); } +static int adv7533_attach_dsi (struct adv7511 *adv7511) +{ +struct device *dev = &adv7511->i2c_main->dev; +struct mipi_dsi_device *dsi; +struct mipi_dsi_host *host; +int ret; + + host =of_find_mipi_dsi_host_by_node (adv7511->host_node); +if (!host) { +dev_err (dev,"failed to find dsi host\n" ); +return -EPROBE_DEFER ; + } + +/* can adv7533 virtual channel be non-zero? */ + dsi =mipi_dsi_new_dummy (host,0 ); +if (IS_ERR (dsi)) { +dev_err (dev,"failed to create dummy dsi device\n" ); + ret =PTR_ERR (dsi); + goto err_dsi_device; + } + + adv7511->dsi = dsi; + + dsi->lanes = adv7511->num_dsi_lanes; + dsi->format =MIPI_DSI_FMT_RGB888 ; + dsi->mode_flags =MIPI_DSI_MODE_VIDEO |MIPI_DSI_MODE_VIDEO_SYNC_PULSE + |MIPI_DSI_MODE_EOT_PACKET |MIPI_DSI_MODE_VIDEO_HSE ; + + ret =mipi_dsi_attach (dsi); +if (ret <0 ) { +dev_err (dev,"failed to attach dsi to host\n" ); + goto err_dsi_attach; + } + +return 0 ; + +err_dsi_attach: +mipi_dsi_unregister_device (dsi); +err_dsi_device: +return ret; +} +static int adv7533_bridge_attach (struct drm_bridge *bridge) {struct adv7511 *adv =bridge_to_adv7511 (bridge);
@@ -980,6 +1031,8 @@ static int adv7533_bridge_attach(struct drm_bridge *bridge)drm_helper_hpd_irq_event (adv->connector.dev); +adv7533_attach_dsi (adv); +return ret; }
@@ -1079,6 +1132,41 @@ static int adv7511_parse_dt(struct device_node *np,return 0 ; } +static int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv7511) +{ +u32 num_lanes; +struct device_node *endpoint; + +of_property_read_u32 (np,"adi,dsi-lanes" , &num_lanes); + +if (num_lanes <1 || num_lanes >4 ) +return -EINVAL ; + + adv7511->num_dsi_lanes = num_lanes; + + endpoint =of_graph_get_next_endpoint (np,NULL ); +if (!endpoint) { +DRM_ERROR ("adv dsi input endpoint not found\n" ); +return -ENODEV ; + } + + adv7511->host_node =of_graph_get_remote_port_parent (endpoint); +if (!adv7511->host_node) { +DRM_ERROR ("dsi host node not found\n" ); +of_node_put (endpoint); +return -ENODEV ; + } + +of_node_put (endpoint); +of_node_put (adv7511->host_node); + +/* TODO: Check if these need to be parsed by DT or not */ + adv7511->rgb = true; + adv7511->embedded_sync = false; + +return 0 ; +} +static const int edid_i2c_addr =0x7e ;static const int packet_i2c_addr =0x70 ;static const int cec_i2c_addr =0x78 ;
@@ -1121,11 +1209,12 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)memset (&link_config,0 ,sizeof (link_config)); -if (adv7511->type ==ADV7511 ) { +if (adv7511->type ==ADV7511 ) ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; - } +else + ret =adv7533_parse_dt (dev->of_node, adv7511); +if (ret) +return ret;/* * The power down GPIO is optional. If present, toggle it from active to
@@ -1247,8 +1336,11 @@ static int adv7511_remove(struct i2c_client *i2c)kfree (adv7511->edid); -if (adv7511->type ==ADV7533 ) +if (adv7511->type ==ADV7533 ) { +mipi_dsi_detach (adv7511->dsi); +mipi_dsi_unregister_device (adv7511->dsi);drm_bridge_remove (&adv7511->bridge); + }return 0 ; }
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
v2 cover drm/i2c: adv7511: ADV7533 support
In reply to Archit TanejaADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
This series adds support for ADV7533. Unlike ADV7511 that's modelled as a drm i2c slave encoder, ADV7533 is a drm_bridge object. The bridge ops further create a HDMI type connector device for the chip's output.
Changes in v2:
- The last patch in the series has changed completely. Instead of using the dummy mipi dsi device usage, we now have two separate drivers for i2c and dsi components of the chip. This was discussed in depth (without a final conclusion) here:
https://lkml.org/lkml/2015/6/30/42
With this approach, we wouldn't need to create dummy dsi devices, but we'd have two DT nodes for two different parts of the same chip
- Use of_device_get_match_data() to simplify things.
The older series (using dummy mipi dsi devices) is here:
http://lists.freedesktop.org/archives/dri-devel/2015-July/087088.html
Can we please decide on one of these approaches?
Archit Taneja (4):
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Refactor encoder slave functions drm/i2c: adv7511: Add drm_bridge/connector for ADV7533 drm/i2c: adv7511: Add dsi driver for adv7533
Lars-Peter Clausen (1):
drm/i2c: adv7511: Initial support for adv7533
drivers/gpu/drm/i2c/adv7511.c | 480 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 434 insertions(+), 46 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v2 1/5 drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled
When the adv7511 i2c client doesn't have an interrupt line, we observe a deadlock on caused by trying to lock drm device's mode_config.mutex twice in the same context.
Here is the sequence that causes it:
ioctl DRM_IOCTL_MODE_GETCONNECTOR from userspace
drm_mode_getconnector (acquires mode_config mutex)
connector->fill_modes()
drm_helper_probe_single_connector_modes
connector_funcs->get_modes
adv7511_encoder_get_modes
adv7511_get_edid_block
adv7511_irq_process
drm_helper_hpd_irq_event (acquires mode_config mutex again)In adv7511_irq_process, don't call drm_helper_hpd_irq_event when not called from interrupt context. It doesn't serve any purpose there anyway.
--- drivers/gpu/drm/i2c/adv7511.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +4 -4
@@ -422,7 +422,7 @@ static bool adv7511_hpd(struct adv7511 *adv7511)return false; } -static int adv7511_irq_process (struct adv7511 *adv7511) +static int adv7511_irq_process (struct adv7511 *adv7511,bool process_hpd) {unsigned int irq0, irq1;int ret;
@@ -438,7 +438,7 @@ static int adv7511_irq_process(struct adv7511 *adv7511)regmap_write (adv7511->regmap,ADV7511_REG_INT (0 ), irq0);regmap_write (adv7511->regmap,ADV7511_REG_INT (1 ), irq1); -if (irq0 &ADV7511_INT0_HDP && adv7511->encoder) +if (process_hpd && irq0 &ADV7511_INT0_HDP && adv7511->encoder)drm_helper_hpd_irq_event (adv7511->encoder->dev);if (irq0 &ADV7511_INT0_EDID_READY || irq1 &ADV7511_INT1_DDC_ERROR ) {
@@ -456,7 +456,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid)struct adv7511 *adv7511 = devid;int ret; - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, true);return ret <0 ?IRQ_NONE :IRQ_HANDLED ; }
@@ -473,7 +473,7 @@ static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout) adv7511->edid_read, msecs_to_jiffies(timeout)); }else {for (; timeout >0 ; timeout -=25 ) { - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, false);if (ret <0 )break ;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v2 2/5 drm/i2c: adv7511: Initial support for adv7533
In reply to Archit TanejaFrom: Lars-Peter Clausen <[email protected]>
ADV7533 is a DSI to HDMI encoder chip. It is a derivative of ADV7511, with additional blocks to translate input DSI data to parallel RGB data. Besides the ADV7511 i2c register map, it has additional registers that require to be configured to activate the DSI blocks.
Use DT compatible strings to populate the adv7533 type enum. Add minimal register configurations belonging to the DSI/CEC register map.
--- drivers/gpu/drm/i2c/adv7511.c | 141 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 122 insertions(+), 19 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +122 -19
@@ -20,12 +20,18 @@#include "adv7511.h" +enum adv7511_type { +ADV7511 , +ADV7533 , +}; +struct adv7511 {struct i2c_client *i2c_main;struct i2c_client *i2c_edid; +struct i2c_client *i2c_cec;struct regmap *regmap; -struct regmap *packet_memory_regmap; +struct regmap *regmap_cec;enum drm_connector_status status;bool powered;
@@ -46,6 +52,8 @@ struct adv7511 {struct edid *edid;struct gpio_desc *gpio_pd; + +enum adv7511_type type; };static struct adv7511 *encoder_to_adv7511 (struct drm_encoder *encoder)
@@ -66,6 +74,23 @@ static const struct reg_default adv7511_fixed_registers[] = { { 0x55, 0x02 }, }; +/* ADI recommended values for proper operation. */ +static const struct reg_default adv7533_fixed_registers[] = { + {0x16 ,0x20 }, + {0x9a ,0xe0 }, + {0xba ,0x70 }, + {0xde ,0x82 }, + {0xe4 ,0x40 }, + {0xe5 ,0x80 }, +}; + +static const struct reg_default adv7533_cec_fixed_registers[] = { + {0x15 ,0xd0 }, + {0x17 ,0xd0 }, + {0x24 ,0x20 }, + {0x57 ,0x11 }, +}; +/* ----------------------------------------------------------------------------- * Register access */
@@ -158,6 +183,15 @@ static const struct regmap_config adv7511_regmap_config = { .volatile_reg = adv7511_register_volatile, }; +static const struct regmap_config adv7533_cec_regmap_config = { + .reg_bits =8 , + .val_bits =8 , + + .max_register =0xff , + .cache_type =REGCACHE_RBTREE , +}; + +/* ----------------------------------------------------------------------------- * Hardware configuration */
@@ -358,6 +392,25 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, adv7511->rgb = config->input_colorspace ==HDMI_COLORSPACE_RGB ; } +static void adv7511_dsi_receiver_dpms (struct adv7511 *adv7511) +{ +if (adv7511->type !=ADV7533 ) +return ; + +if (adv7511->powered) { +/* set number of dsi lanes (hardcoded to 4 for now) */ +regmap_write (adv7511->regmap_cec,0x1c ,0x4 <<4 ); +/* disable internal timing generator */ +regmap_write (adv7511->regmap_cec,0x27 ,0x0b ); +/* enable hdmi */ +regmap_write (adv7511->regmap_cec,0x03 ,0x89 ); +/* disable test mode */ +regmap_write (adv7511->regmap_cec,0x55 ,0x00 ); + }else { +regmap_write (adv7511->regmap_cec,0x03 ,0x0b ); + } +} +static void adv7511_power_on (struct adv7511 *adv7511) { adv7511->current_edid_segment =-1 ;
@@ -387,6 +440,8 @@ static void adv7511_power_on(struct adv7511 *adv7511)regcache_sync (adv7511->regmap); adv7511->powered = true; + +adv7511_dsi_receiver_dpms (adv7511); }static void adv7511_power_off (struct adv7511 *adv7511)
@@ -398,6 +453,8 @@ static void adv7511_power_off(struct adv7511 *adv7511)regcache_mark_dirty (adv7511->regmap); adv7511->powered = false; + +adv7511_dsi_receiver_dpms (adv7511); }/* -----------------------------------------------------------------------------
@@ -567,6 +624,9 @@ static int adv7511_get_modes(struct drm_encoder *encoder,/* Reading the EDID only works if the device is powered */ if (!adv7511->powered) { +regmap_update_bits (adv7511->regmap,ADV7511_REG_POWER2 , +ADV7511_REG_POWER2_HDP_SRC_MASK , +ADV7511_REG_POWER2_HDP_SRC_NONE );regmap_write (adv7511->regmap,ADV7511_REG_INT (0 ),ADV7511_INT0_EDID_READY ); regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
@@ -770,8 +830,6 @@ static int adv7511_parse_dt(struct device_node *np,const char *str;int ret; -memset (config,0 ,sizeof (*config)); -of_property_read_u32 (np,"adi,input-depth" , &config->input_color_depth);if (config->input_color_depth !=8 && config->input_color_depth !=10 && config->input_color_depth !=12 )
@@ -871,9 +929,18 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) adv7511->powered = false; adv7511->status = connector_status_disconnected; - ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; +if (dev->of_node) + adv7511->type =of_device_get_match_data (dev); +else + adv7511->type = id->driver_data; + +memset (&link_config,0 ,sizeof (link_config)); + +if (adv7511->type ==ADV7511 ) { + ret =adv7511_parse_dt (dev->of_node, &link_config); +if (ret) +return ret; + }/* * The power down GPIO is optional. If present, toggle it from active to
@@ -897,10 +964,19 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)return ret;dev_dbg (dev,"Rev. %d\n" , val); - ret =regmap_register_patch (adv7511->regmap, adv7511_fixed_registers, -ARRAY_SIZE (adv7511_fixed_registers)); -if (ret) -return ret; +if (adv7511->type ==ADV7511 ) { + ret =regmap_register_patch (adv7511->regmap, + adv7511_fixed_registers, +ARRAY_SIZE (adv7511_fixed_registers)); +if (ret) +return ret; + }else { + ret =regmap_register_patch (adv7511->regmap, + adv7533_fixed_registers, +ARRAY_SIZE (adv7533_fixed_registers)); +if (ret) +return ret; + }regmap_write (adv7511->regmap,ADV7511_REG_EDID_I2C_ADDR , edid_i2c_addr); regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
@@ -913,6 +989,27 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)if (!adv7511->i2c_edid)return -ENOMEM ; + adv7511->i2c_cec =i2c_new_dummy (i2c->adapter, cec_i2c_addr >>1 ); +if (!adv7511->i2c_cec) { + ret = -ENOMEM ; + goto err_i2c_unregister_edid; + } + + adv7511->regmap_cec =devm_regmap_init_i2c (adv7511->i2c_cec, + &adv7533_cec_regmap_config); +if (IS_ERR (adv7511->regmap_cec)) { + ret =PTR_ERR (adv7511->regmap_cec); + goto err_i2c_unregister_cec; + } + +if (adv7511->type ==ADV7533 ) { + ret =regmap_register_patch (adv7511->regmap_cec, + adv7533_cec_fixed_registers, +ARRAY_SIZE (adv7533_cec_fixed_registers)); +if (ret) +return ret; + } +if (i2c->irq) {init_waitqueue_head (&adv7511->wq);
@@ -921,7 +1018,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)IRQF_ONESHOT ,dev_name (dev), adv7511);if (ret) - goto err_i2c_unregister_device; + goto err_i2c_unregister_cec; }/* CEC is unused for now */
@@ -932,11 +1029,14 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)i2c_set_clientdata (i2c, adv7511); -adv7511_set_link_config (adv7511, &link_config); +if (adv7511->type ==ADV7511 ) +adv7511_set_link_config (adv7511, &link_config);return 0 ; -err_i2c_unregister_device: +err_i2c_unregister_cec: +i2c_unregister_device (adv7511->i2c_cec); +err_i2c_unregister_edid:i2c_unregister_device (adv7511->i2c_edid);return ret;
@@ -946,6 +1046,7 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +i2c_unregister_device (adv7511->i2c_cec);i2c_unregister_device (adv7511->i2c_edid);kfree (adv7511->edid);
@@ -968,17 +1069,19 @@ static int adv7511_encoder_init(struct i2c_client *i2c, struct drm_device *dev, }static const struct i2c_device_id adv7511_i2c_ids[] = { - {"adv7511" ,0 }, - {"adv7511w" ,0 }, - {"adv7513" ,0 }, + {"adv7511" ,ADV7511 }, + {"adv7511w" ,ADV7511 }, + {"adv7513" ,ADV7511 }, + {"adv7533" ,ADV7533 }, { } };MODULE_DEVICE_TABLE (i2c, adv7511_i2c_ids);static const struct of_device_id adv7511_of_ids[] = { - { .compatible ="adi,adv7511" , }, - { .compatible ="adi,adv7511w" , }, - { .compatible ="adi,adv7513" , }, + { .compatible ="adi,adv7511" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7511w" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7513" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7533-i2c" , .data = (void *)ADV7533 }, { } };MODULE_DEVICE_TABLE (of, adv7511_of_ids);
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 3/5 drm/i2c: adv7511: Refactor encoder slave functions
In reply to Archit TanejaADV7511 is represented as an i2c drm slave encoder device. ADV7533, on the other hand, is going be a normal i2c client device creating bridge and connector entities.
Move the code in encoder slave functions to generate helpers that are agnostic to the drm object type. These helpers will later also be used by bridge and connecter helper functions.
--- drivers/gpu/drm/i2c/adv7511.c | 80 ++++++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 23 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +57 -23
@@ -612,13 +612,11 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, }/* ----------------------------------------------------------------------------- -* Encoder operations +* ADV75xx helpers */ - -static int adv7511_get_modes (struct drm_encoder *encoder, -struct drm_connector *connector) +static int adv7511_get_modes (struct adv7511 *adv7511, +struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);struct edid *edid;unsigned int count;
@@ -656,21 +654,10 @@ static int adv7511_get_modes(struct drm_encoder *encoder,return count; } -static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) -{ -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); - -if (mode ==DRM_MODE_DPMS_ON ) -adv7511_power_on (adv7511); -else -adv7511_power_off (adv7511); -} -static enum drm_connector_status -adv7511_encoder_detect (struct drm_encoder *encoder, +adv7511_detect (struct adv7511 *adv7511,struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);enum drm_connector_status status;unsigned int val;bool hpd;
@@ -694,7 +681,7 @@ adv7511_encoder_detect(struct drm_encoder *encoder,if (status == connector_status_connected && hpd && adv7511->powered) {regcache_mark_dirty (adv7511->regmap);adv7511_power_on (adv7511); -adv7511_get_modes (encoder, connector); +adv7511_get_modes (adv7511, connector);if (adv7511->status == connector_status_connected) status = connector_status_disconnected; }else {
@@ -708,8 +695,8 @@ adv7511_encoder_detect(struct drm_encoder *encoder,return status; } -static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, -struct drm_display_mode *mode) +static int adv7511_mode_valid (struct adv7511 *adv7511, +const struct drm_display_mode *mode) {if (mode->clock >165000 )return MODE_CLOCK_HIGH ;
@@ -717,11 +704,10 @@ static int adv7511_encoder_mode_valid(struct drm_encoder *encoder,return MODE_OK ; } -static void adv7511_encoder_mode_set (struct drm_encoder *encoder, +static void adv7511_mode_set (struct adv7511 *adv7511,struct drm_display_mode *mode,struct drm_display_mode *adj_mode) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);unsigned int low_refresh_rate;unsigned int hsync_polarity =0 ;unsigned int vsync_polarity =0 ;
@@ -812,12 +798,60 @@ static void adv7511_encoder_mode_set(struct drm_encoder *encoder, adv7511->f_tmds = mode->clock; } +/* ----------------------------------------------------------------------------- +* Encoder operations +*/ + +static int adv7511_encoder_get_modes (struct drm_encoder *encoder, +struct drm_connector *connector) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_get_modes (adv7511, connector); +} + +static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +if (mode ==DRM_MODE_DPMS_ON ) +adv7511_power_on (adv7511); +else +adv7511_power_off (adv7511); +} + +static enum drm_connector_status +adv7511_encoder_detect (struct drm_encoder *encoder, +struct drm_connector *connector) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_detect (adv7511, connector); +} + +static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, +struct drm_display_mode *mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +return adv7511_mode_valid (adv7511, mode); +} + +static void adv7511_encoder_mode_set (struct drm_encoder *encoder, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) +{ +struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); + +adv7511_mode_set (adv7511, mode, adj_mode); +} +static struct drm_encoder_slave_funcs adv7511_encoder_funcs = { .dpms = adv7511_encoder_dpms, .mode_valid = adv7511_encoder_mode_valid, .mode_set = adv7511_encoder_mode_set, .detect = adv7511_encoder_detect, - .get_modes = adv7511_get_modes, + .get_modes = adv7511_encoder_get_modes, };/* -----------------------------------------------------------------------------
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 4/5 drm/i2c: adv7511: Add drm_bridge/connector for ADV7533
In reply to Archit TanejaCreate bridge and connector helper functions. These internally refer to the ADV75xx helper functions.
The driver registers a drm_bridge object during probe. The bridge, in turn registers a HDMI connector when a user attaches the bridge.
Therefore, when the device type is ADV7533, we create bridge and connector entities, and when it's ADV7511, we create a slave encoder as before.
Since the i2c driver is still wrapped around by the drm_i2c_slave_encoder struct. We make sure the encoder_init op returns an error when the device type is ADV7533.
--- drivers/gpu/drm/i2c/adv7511.c | 155 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+)
drivers/gpu/drm/i2c/adv7511.c +155 -0
@@ -17,6 +17,8 @@#include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> #include <drm/drm_encoder_slave.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include "adv7511.h"
@@ -44,6 +46,9 @@ struct adv7511 {wait_queue_head_t wq;struct drm_encoder *encoder; +struct drm_connector connector; +struct drm_bridge bridge; +bool embedded_sync;enum adv7511_sync_polarity vsync_polarity;enum adv7511_sync_polarity hsync_polarity;
@@ -855,6 +860,139 @@ static struct drm_encoder_slave_funcs adv7511_encoder_funcs = { };/* ----------------------------------------------------------------------------- +* Bridge and connector functions +*/ + +static struct adv7511 *connector_to_adv7511 (struct drm_connector *connector) +{ + return container_of(connector, struct adv7511, connector); +} + +/* Connector helper functions */ +static int adv7533_connector_get_modes (struct drm_connector *connector) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_get_modes (adv, connector); +} + +static struct drm_encoder * +adv7533_connector_best_encoder (struct drm_connector *connector) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv->bridge.encoder; +} + +static enum drm_mode_status +adv7533_connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_mode_valid (adv, mode); +} + +static struct drm_connector_helper_funcs adv7533_connector_helper_funcs = { + .get_modes = adv7533_connector_get_modes, + .best_encoder = adv7533_connector_best_encoder, + .mode_valid = adv7533_connector_mode_valid, +}; + +static enum drm_connector_status +adv7533_connector_detect (struct drm_connector *connector,bool force) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_detect (adv, connector); +} + +static struct drm_connector_funcs adv7533_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = adv7533_connector_detect, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +/* Bridge funcs */ +static struct adv7511 *bridge_to_adv7511 (struct drm_bridge *bridge) +{ + return container_of(bridge, struct adv7511, bridge); +} + +static void adv7533_bridge_pre_enable (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_power_on (adv); +} + +static void adv7533_bridge_post_disable (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_power_off (adv); +} + +static void adv7533_bridge_enable (struct drm_bridge *bridge) +{ +} + +static void adv7533_bridge_disable (struct drm_bridge *bridge) +{ +} + +static void adv7533_bridge_mode_set (struct drm_bridge *bridge, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_mode_set (adv, mode, adj_mode); +} + +static int adv7533_bridge_attach (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); +int ret; + + adv->encoder = bridge->encoder; + +if (!bridge->encoder) { +DRM_ERROR ("Parent encoder object not found" ); +return -ENODEV ; + } + + adv->connector.polled =DRM_CONNECTOR_POLL_HPD ; + ret =drm_connector_init (bridge->dev, &adv->connector, + &adv7533_connector_funcs,DRM_MODE_CONNECTOR_HDMIA ); +if (ret) { +DRM_ERROR ("Failed to initialize connector with drm\n" ); +return ret; + } +drm_connector_helper_add (&adv->connector, + &adv7533_connector_helper_funcs); +drm_connector_register (&adv->connector); +drm_mode_connector_attach_encoder (&adv->connector, adv->encoder); + +drm_helper_hpd_irq_event (adv->connector.dev); + +return ret; +} + +static struct drm_bridge_funcs adv7533_bridge_funcs = { + .pre_enable = adv7533_bridge_pre_enable, + .enable = adv7533_bridge_enable, + .disable = adv7533_bridge_disable, + .post_disable = adv7533_bridge_post_disable, + .mode_set = adv7533_bridge_mode_set, + .attach = adv7533_bridge_attach, +}; + +/* ----------------------------------------------------------------------------- * Probe & remove */
@@ -1066,6 +1204,17 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)if (adv7511->type ==ADV7511 )adv7511_set_link_config (adv7511, &link_config); +if (adv7511->type ==ADV7533 ) { + adv7511->bridge.funcs = &adv7533_bridge_funcs; + adv7511->bridge.of_node = dev->of_node; + + ret =drm_bridge_add (&adv7511->bridge); +if (ret) { +dev_err (dev,"failed to add adv7533 bridge\n" ); + goto err_i2c_unregister_cec; + } + } +return 0 ; err_i2c_unregister_cec:
@@ -1085,6 +1234,9 @@ static int adv7511_remove(struct i2c_client *i2c)kfree (adv7511->edid); +if (adv7511->type ==ADV7533 ) +drm_bridge_remove (&adv7511->bridge); +return 0 ; }
@@ -1094,6 +1246,9 @@ static int adv7511_encoder_init(struct i2c_client *i2c, struct drm_device *dev,struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +if (adv7511->type ==ADV7533 ) +return -ENODEV ; + encoder->slave_priv = adv7511; encoder->slave_funcs = &adv7511_encoder_funcs;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 5/5 drm/i2c: adv7511: Add dsi driver for adv7533
In reply to Archit TanejaAdd a separate mipi_dsi_driver for adv7533. In the case of this chip, both the i2c and dsi drivers will operate together.
Both the drivers are expected to use the same per-device driver data struct. The i2c driver takes the responsibility of allocating the struct, and the dsi device gets a pointer to it by getting the corresponding i2c client device's data.
--- drivers/gpu/drm/i2c/adv7511.c | 98 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-)
drivers/gpu/drm/i2c/adv7511.c +97 -1
@@ -19,6 +19,7 @@#include <drm/drm_encoder_slave.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_mipi_dsi.h> #include "adv7511.h"
@@ -58,6 +59,9 @@ struct adv7511 {struct gpio_desc *gpio_pd; +struct mipi_dsi_device *dsi; +int num_dsi_lanes; +enum adv7511_type type; };
@@ -403,8 +407,10 @@ static void adv7511_dsi_receiver_dpms(struct adv7511 *adv7511)return ;if (adv7511->powered) { +struct mipi_dsi_device *dsi = adv7511->dsi; +/* set number of dsi lanes (hardcoded to 4 for now) */ -regmap_write (adv7511->regmap_cec,0x1c ,0x4 <<4 ); +regmap_write (adv7511->regmap_cec,0x1c , dsi->lanes <<4 );/* disable internal timing generator */ regmap_write (adv7511->regmap_cec,0x27 ,0x0b );/* enable hdmi */
@@ -1289,8 +1295,97 @@ static struct drm_i2c_encoder_driver adv7511_driver = { .encoder_init = adv7511_encoder_init, }; +/* Driver for the DSI component within the chip */ +static int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv7511) +{ +u32 num_lanes; + +of_property_read_u32 (np,"adi,dsi-lanes" , &num_lanes); + +if (num_lanes <1 || num_lanes >4 ) +return -EINVAL ; + + adv7511->num_dsi_lanes = num_lanes; + +/* TODO: Check if these need to be parsed by DT or not */ + adv7511->rgb = true; + adv7511->embedded_sync = false; + +return 0 ; +} + +static int adv7533_probe (struct mipi_dsi_device *dsi) +{ +struct device *dev = &dsi->dev; +struct adv7511 *adv7511; +struct device_node *np = dsi->dev.of_node; +struct device_node *i2c_node; +struct i2c_client *i2c; +int ret; + + i2c_node =of_parse_phandle (np,"i2c-control" ,0 ); +if (!i2c_node) +return -ENODEV ; + + i2c =of_find_i2c_device_by_node (i2c_node); +if (!i2c) +return -EPROBE_DEFER ; + + adv7511 =i2c_get_clientdata (i2c); +if (!adv7511) +return -ENODEV ; + +/* this sets up link with the i2c driver */ + adv7511->dsi = dsi; + +mipi_dsi_set_drvdata (dsi, adv7511); + + ret =adv7533_parse_dt (np, adv7511); +if (ret) +return ret; + + dsi->lanes = adv7511->num_dsi_lanes; + dsi->format =MIPI_DSI_FMT_RGB888 ; + dsi->mode_flags =MIPI_DSI_MODE_VIDEO |MIPI_DSI_MODE_VIDEO_SYNC_PULSE + |MIPI_DSI_MODE_EOT_PACKET |MIPI_DSI_MODE_VIDEO_HSE ; + +return mipi_dsi_attach (dsi); +} + +static int adv7533_remove (struct mipi_dsi_device *dsi) +{ +mipi_dsi_detach (dsi); + +return 0 ; +} + +static const struct of_device_id adv7533_of_match[] = { + { .compatible ="adi,adv7533-dsi" }, + { } +}; +MODULE_DEVICE_TABLE (of, adv7533_of_match); + +static struct mipi_dsi_driver adv7533_driver = { + .probe = adv7533_probe, + .remove = adv7533_remove, + .driver = { + .name ="adv7533" , + .of_match_table = adv7533_of_match, + }, +}; +static int __init adv7511_init (void ) { +int ret; + +/* +* not bailing out here because adv7511 variant won't +* need a DSI driver +*/ + ret =mipi_dsi_driver_register (&adv7533_driver); +if (ret) +DRM_DEBUG ("mipi driver register failed %d\n" , ret); +return drm_i2c_encoder_register (THIS_MODULE , &adv7511_driver); }module_init (adv7511_init);
@@ -1298,6 +1393,7 @@ module_init(adv7511_init); static void __exit adv7511_exit(void) {drm_i2c_encoder_unregister (&adv7511_driver); +mipi_dsi_driver_unregister (&adv7533_driver); }module_exit (adv7511_exit);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
v3 cover drm/i2c: adv7511: ADV7533 support
In reply to Archit TanejaADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Tested on ADV7533 chips on DB410c. It should work on the Hikey board too. I'd appreaciate if someone could test it on a ADV7511 platform since I don't have one.
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html
[3]
https://lkml.org/lkml/2016/2/12/67
[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.html
[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.html
Archit Taneja (7):
drm/i2c: adv7511: Convert to drm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7511: Create a MIPI DSI device
drm/i2c: adv7511: Use internal timing generator drm/i2c: adv7511: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533
.../bindings/display/bridge/adi,adv7511.txt | 25 +- drivers/gpu/drm/i2c/adv7511.c | 539 +++++++++++++++++---- 2 files changed, 476 insertions(+), 88 deletions(-)
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v3 1/7 drm/i2c: adv7511: Convert to drm_bridge
We don't want to use the old i2c slave encoder interface anymore.
Remove that and make the i2c driver create a drm_bridge entity instead. Converting to bridges helps because the kms drivers don't need to exract encoder slave ops from this driver and use it within their own encoder/connector ops.
The driver now creates its own connector when a kms driver attaches itself to the bridge. Therefore, kms drivers don't need to create their own connectors anymore.
The old encoder slave ops are now used by the new bridge and connector entities.
---
v3:
- Remove calls to connector_register and hpd helper in bridge_attach
- Remove noop bridge ops
drivers/gpu/drm/i2c/adv7511.c | 222 ++++++++++++++++++++++++++++-------------- 1 file changed, 148 insertions(+), 74 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +148 -74
@@ -14,9 +14,10 @@#include <linux/slab.h> #include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> -#include <drm/drm_encoder_slave.h> #include "adv7511.h"
@@ -36,7 +37,8 @@ struct adv7511 {bool edid_read;wait_queue_head_t wq; -struct drm_encoder *encoder; +struct drm_bridge bridge; +struct drm_connector connector;bool embedded_sync;enum adv7511_sync_polarity vsync_polarity;
@@ -48,11 +50,6 @@ struct adv7511 {struct gpio_desc *gpio_pd; }; -static struct adv7511 *encoder_to_adv7511 (struct drm_encoder *encoder) -{ -return to_encoder_slave (encoder)->slave_priv; -} -/* ADI recommended values for proper operation. */ static const struct reg_sequence adv7511_fixed_registers[] = { {0x98 ,0x03 },
@@ -446,8 +443,8 @@ static int adv7511_irq_process(struct adv7511 *adv7511)regmap_write (adv7511->regmap,ADV7511_REG_INT (0 ), irq0);regmap_write (adv7511->regmap,ADV7511_REG_INT (1 ), irq1); -if (irq0 &ADV7511_INT0_HPD && adv7511->encoder) -drm_helper_hpd_irq_event (adv7511->encoder->dev); +if (irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder) +drm_helper_hpd_irq_event (adv7511->connector.dev);if (irq0 &ADV7511_INT0_EDID_READY || irq1 &ADV7511_INT1_DDC_ERROR ) { adv7511->edid_read = true;
@@ -563,13 +560,12 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, }/* ----------------------------------------------------------------------------- -* Encoder operations +* ADV75xx helpers */ -static int adv7511_get_modes (struct drm_encoder *encoder, +static int adv7511_get_modes (struct adv7511 *adv7511,struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);struct edid *edid;unsigned int count;
@@ -606,21 +602,9 @@ static int adv7511_get_modes(struct drm_encoder *encoder,return count; } -static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) -{ -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); - -if (mode ==DRM_MODE_DPMS_ON ) -adv7511_power_on (adv7511); -else -adv7511_power_off (adv7511); -} -static enum drm_connector_status -adv7511_encoder_detect (struct drm_encoder *encoder, -struct drm_connector *connector) +adv7511_detect (struct adv7511 *adv7511,struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);enum drm_connector_status status;unsigned int val;bool hpd;
@@ -644,7 +628,7 @@ adv7511_encoder_detect(struct drm_encoder *encoder,if (status == connector_status_connected && hpd && adv7511->powered) {regcache_mark_dirty (adv7511->regmap);adv7511_power_on (adv7511); -adv7511_get_modes (encoder, connector); +adv7511_get_modes (adv7511, connector);if (adv7511->status == connector_status_connected) status = connector_status_disconnected; }else {
@@ -658,8 +642,8 @@ adv7511_encoder_detect(struct drm_encoder *encoder,return status; } -static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, -struct drm_display_mode *mode) +static int adv7511_mode_valid (struct adv7511 *adv7511, +struct drm_display_mode *mode) {if (mode->clock >165000 )return MODE_CLOCK_HIGH ;
@@ -667,11 +651,10 @@ static int adv7511_encoder_mode_valid(struct drm_encoder *encoder,return MODE_OK ; } -static void adv7511_encoder_mode_set (struct drm_encoder *encoder, -struct drm_display_mode *mode, -struct drm_display_mode *adj_mode) +static void adv7511_mode_set (struct adv7511 *adv7511, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);unsigned int low_refresh_rate;unsigned int hsync_polarity =0 ;unsigned int vsync_polarity =0 ;
@@ -762,12 +745,120 @@ static void adv7511_encoder_mode_set(struct drm_encoder *encoder, adv7511->f_tmds = mode->clock; } -static const struct drm_encoder_slave_funcs adv7511_encoder_funcs = { - .dpms = adv7511_encoder_dpms, - .mode_valid = adv7511_encoder_mode_valid, - .mode_set = adv7511_encoder_mode_set, - .detect = adv7511_encoder_detect, - .get_modes = adv7511_get_modes, +/* Connector funcs */ +static struct adv7511 *connector_to_adv7511 (struct drm_connector *connector) +{ + return container_of(connector, struct adv7511, connector); +} + +static int adv7511_connector_get_modes (struct drm_connector *connector) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_get_modes (adv, connector); +} + +static struct drm_encoder * +adv7511_connector_best_encoder (struct drm_connector *connector) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv->bridge.encoder; +} + +static enum drm_mode_status +adv7511_connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_mode_valid (adv, mode); +} + +static struct drm_connector_helper_funcs adv7511_connector_helper_funcs = { + .get_modes = adv7511_connector_get_modes, + .best_encoder = adv7511_connector_best_encoder, + .mode_valid = adv7511_connector_mode_valid, +}; + +static enum drm_connector_status +adv7511_connector_detect (struct drm_connector *connector,bool force) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_detect (adv, connector); +} + +static struct drm_connector_funcs adv7511_connector_funcs = { + .dpms = drm_atomic_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = adv7511_connector_detect, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +/* Bridge funcs */ +static struct adv7511 *bridge_to_adv7511 (struct drm_bridge *bridge) +{ + return container_of(bridge, struct adv7511, bridge); +} + +static void adv7511_bridge_enable (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_power_on (adv); +} + +static void adv7511_bridge_disable (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_power_off (adv); +} + +static void adv7511_bridge_mode_set (struct drm_bridge *bridge, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_mode_set (adv, mode, adj_mode); +} + +static int adv7511_bridge_attach (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); +int ret; + +if (!bridge->encoder) { +DRM_ERROR ("Parent encoder object not found" ); +return -ENODEV ; + } + + adv->connector.polled =DRM_CONNECTOR_POLL_HPD ; + + ret =drm_connector_init (bridge->dev, &adv->connector, + &adv7511_connector_funcs, +DRM_MODE_CONNECTOR_HDMIA ); +if (ret) { +DRM_ERROR ("Failed to initialize connector with drm\n" ); +return ret; + } +drm_connector_helper_add (&adv->connector, + &adv7511_connector_helper_funcs); +drm_mode_connector_attach_encoder (&adv->connector, bridge->encoder); + +return ret; +} + +static struct drm_bridge_funcs adv7511_bridge_funcs = { + .enable = adv7511_bridge_enable, + .disable = adv7511_bridge_disable, + .mode_set = adv7511_bridge_mode_set, + .attach = adv7511_bridge_attach, };/* -----------------------------------------------------------------------------
@@ -944,6 +1035,15 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)adv7511_set_link_config (adv7511, &link_config); + adv7511->bridge.funcs = &adv7511_bridge_funcs; + adv7511->bridge.of_node = dev->of_node; + + ret =drm_bridge_add (&adv7511->bridge); +if (ret) { +dev_err (dev,"failed to add adv7511 bridge\n" ); + goto err_i2c_unregister_device; + } +return 0 ; err_i2c_unregister_device:
@@ -956,6 +1056,8 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +drm_bridge_remove (&adv7511->bridge); +i2c_unregister_device (adv7511->i2c_edid);kfree (adv7511->edid);
@@ -963,20 +1065,6 @@ static int adv7511_remove(struct i2c_client *i2c)return 0 ; } -static int adv7511_encoder_init (struct i2c_client *i2c,struct drm_device *dev, -struct drm_encoder_slave *encoder) -{ - -struct adv7511 *adv7511 =i2c_get_clientdata (i2c); - - encoder->slave_priv = adv7511; - encoder->slave_funcs = &adv7511_encoder_funcs; - - adv7511->encoder = &encoder->base; - -return 0 ; -} -static const struct i2c_device_id adv7511_i2c_ids[] = { {"adv7511" ,0 }, {"adv7511w" ,0 },
@@ -993,31 +1081,17 @@ static const struct of_device_id adv7511_of_ids[] = { };MODULE_DEVICE_TABLE (of, adv7511_of_ids); -static struct drm_i2c_encoder_driver adv7511_driver = { - .i2c_driver = { - .driver = { - .name ="adv7511" , - .of_match_table = adv7511_of_ids, - }, - .id_table = adv7511_i2c_ids, - .probe = adv7511_probe, - .remove = adv7511_remove, +static struct i2c_driver adv7511_driver = { + .driver = { + .name ="adv7511" , + .of_match_table = adv7511_of_ids, }, - - .encoder_init = adv7511_encoder_init, + .id_table = adv7511_i2c_ids, + .probe = adv7511_probe, + .remove = adv7511_remove, }; -static int __init adv7511_init (void ) -{ -return drm_i2c_encoder_register (THIS_MODULE , &adv7511_driver); -} -module_init (adv7511_init); - -static void __exit adv7511_exit(void) -{ -drm_i2c_encoder_unregister (&adv7511_driver); -} -module_exit (adv7511_exit); +module_i2c_driver (adv7511_driver);MODULE_AUTHOR ("Lars-Peter Clausen <[email protected]>" );MODULE_DESCRIPTION ("ADV7511 HDMI transmitter driver" );
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v3 2/7 drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled
In reply to Archit TanejaWhen the adv7511 i2c client doesn't have an interrupt line, we observe a deadlock on caused by trying to lock drm device's mode_config.mutex twice in the same context.
Here is the sequence that causes it:
ioctl DRM_IOCTL_MODE_GETCONNECTOR from userspace
drm_mode_getconnector (acquires mode_config mutex)
connector->fill_modes()
drm_helper_probe_single_connector_modes
connector_funcs->get_modes
adv7511_encoder_get_modes
adv7511_get_edid_block
adv7511_irq_process
drm_helper_hpd_irq_event (acquires mode_config mutex again)In adv7511_irq_process, don't call drm_helper_hpd_irq_event when not called from the interrupt handler. It doesn't serve any purpose there anyway.
--- drivers/gpu/drm/i2c/adv7511.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +4 -4
@@ -427,7 +427,7 @@ static bool adv7511_hpd(struct adv7511 *adv7511)return false; } -static int adv7511_irq_process (struct adv7511 *adv7511) +static int adv7511_irq_process (struct adv7511 *adv7511,bool process_hpd) {unsigned int irq0, irq1;int ret;
@@ -443,7 +443,7 @@ static int adv7511_irq_process(struct adv7511 *adv7511)regmap_write (adv7511->regmap,ADV7511_REG_INT (0 ), irq0);regmap_write (adv7511->regmap,ADV7511_REG_INT (1 ), irq1); -if (irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder) +if (process_hpd && irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder)drm_helper_hpd_irq_event (adv7511->connector.dev);if (irq0 &ADV7511_INT0_EDID_READY || irq1 &ADV7511_INT1_DDC_ERROR ) {
@@ -461,7 +461,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid)struct adv7511 *adv7511 = devid;int ret; - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, true);return ret <0 ?IRQ_NONE :IRQ_HANDLED ; }
@@ -478,7 +478,7 @@ static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout) adv7511->edid_read, msecs_to_jiffies(timeout)); }else {for (; timeout >0 ; timeout -=25 ) { - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, false);if (ret <0 )break ;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v3 3/7 drm/i2c: adv7511: Initial support for ADV7533
In reply to Archit TanejaADV7533 is a DSI to HDMI encoder chip. It is a derivative of ADV7511, with additional blocks to translate input DSI data to parallel RGB data. Besides the ADV7511 I2C register map, it has additional registers that require to be configured to activate the DSI Rx block.
Use DT compatible strings to populate the ADV7533 type enum. Add minimal register configurations belonging to the DSI/CEC register map.
Originally worked on by Lars-Peter Clausen <[email protected]>
--- drivers/gpu/drm/i2c/adv7511.c | 138 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 120 insertions(+), 18 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +120 -18
@@ -10,6 +10,7 @@#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/module.h> +#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/slab.h>
@@ -21,12 +22,18 @@#include "adv7511.h" +enum adv7511_type { +ADV7511 , +ADV7533 , +}; +struct adv7511 {struct i2c_client *i2c_main;struct i2c_client *i2c_edid; +struct i2c_client *i2c_cec;struct regmap *regmap; -struct regmap *packet_memory_regmap; +struct regmap *regmap_cec;enum drm_connector_status status;bool powered;
@@ -48,6 +55,8 @@ struct adv7511 {struct edid *edid;struct gpio_desc *gpio_pd; + +enum adv7511_type type; };/* ADI recommended values for proper operation. */
@@ -63,6 +72,22 @@ static const struct reg_sequence adv7511_fixed_registers[] = { { 0x55, 0x02 }, }; +static const struct reg_sequence adv7533_fixed_registers[] = { + {0x16 ,0x20 }, + {0x9a ,0xe0 }, + {0xba ,0x70 }, + {0xde ,0x82 }, + {0xe4 ,0x40 }, + {0xe5 ,0x80 }, +}; + +static const struct reg_sequence adv7533_cec_fixed_registers[] = { + {0x15 ,0xd0 }, + {0x17 ,0xd0 }, + {0x24 ,0x20 }, + {0x57 ,0x11 }, +}; +/* ----------------------------------------------------------------------------- * Register access */
@@ -156,6 +181,15 @@ static const struct regmap_config adv7511_regmap_config = { .volatile_reg = adv7511_register_volatile, }; +static const struct regmap_config adv7533_cec_regmap_config = { + .reg_bits =8 , + .val_bits =8 , + + .max_register =0xff , + .cache_type =REGCACHE_RBTREE , +}; + +/* ----------------------------------------------------------------------------- * Hardware configuration */
@@ -356,6 +390,21 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, adv7511->rgb = config->input_colorspace ==HDMI_COLORSPACE_RGB ; } +static void adv7533_dsi_power_on (struct adv7511 *adv) +{ +/* set number of dsi lanes (hardcoded to 4 for now) */ +regmap_write (adv->regmap_cec,0x1c ,0x4 <<4 ); +/* disable internal timing generator */ +regmap_write (adv->regmap_cec,0x27 ,0x0b ); +/* enable hdmi */ +regmap_write (adv->regmap_cec,0x03 ,0x89 ); +/* disable test mode */ +regmap_write (adv->regmap_cec,0x55 ,0x00 ); + +regmap_register_patch (adv->regmap_cec, adv7533_cec_fixed_registers, +ARRAY_SIZE (adv7533_cec_fixed_registers)); +} +static void adv7511_power_on (struct adv7511 *adv7511) { adv7511->current_edid_segment =-1 ;
@@ -391,9 +440,18 @@ static void adv7511_power_on(struct adv7511 *adv7511)*/ regcache_sync (adv7511->regmap); +if (adv7511->type ==ADV7533 ) +adv7533_dsi_power_on (adv7511); + adv7511->powered = true; } +static void adv7533_dsi_power_off (struct adv7511 *adv) +{ +/* disable hdmi */ +regmap_write (adv->regmap_cec,0x03 ,0x0b ); +} +static void adv7511_power_off (struct adv7511 *adv7511) {/* TODO: setup additional power down modes */
@@ -402,6 +460,9 @@ static void adv7511_power_off(struct adv7511 *adv7511) ADV7511_POWER_POWER_DOWN);regcache_mark_dirty (adv7511->regmap); +if (adv7511->type ==ADV7533 ) +adv7533_dsi_power_off (adv7511); + adv7511->powered = false; }
@@ -871,8 +932,6 @@ static int adv7511_parse_dt(struct device_node *np,const char *str;int ret; -memset (config,0 ,sizeof (*config)); -of_property_read_u32 (np,"adi,input-depth" , &config->input_color_depth);if (config->input_color_depth !=8 && config->input_color_depth !=10 && config->input_color_depth !=12 )
@@ -972,9 +1031,18 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) adv7511->powered = false; adv7511->status = connector_status_disconnected; - ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; +if (dev->of_node) + adv7511->type = (enum adv7511_type )of_device_get_match_data (dev); +else + adv7511->type = id->driver_data; + +memset (&link_config,0 ,sizeof (link_config)); + +if (adv7511->type ==ADV7511 ) { + ret =adv7511_parse_dt (dev->of_node, &link_config); +if (ret) +return ret; + }/* * The power down GPIO is optional. If present, toggle it from active to
@@ -998,8 +1066,15 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)return ret;dev_dbg (dev,"Rev. %d\n" , val); - ret =regmap_register_patch (adv7511->regmap, adv7511_fixed_registers, -ARRAY_SIZE (adv7511_fixed_registers)); +if (adv7511->type ==ADV7511 ) { + ret =regmap_register_patch (adv7511->regmap, + adv7511_fixed_registers, +ARRAY_SIZE (adv7511_fixed_registers)); + }else { + ret =regmap_register_patch (adv7511->regmap, + adv7533_fixed_registers, +ARRAY_SIZE (adv7533_fixed_registers)); + }if (ret)return ret;
@@ -1014,6 +1089,27 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)if (!adv7511->i2c_edid)return -ENOMEM ; + adv7511->i2c_cec =i2c_new_dummy (i2c->adapter, cec_i2c_addr >>1 ); +if (!adv7511->i2c_cec) { + ret = -ENOMEM ; + goto err_i2c_unregister_edid; + } + + adv7511->regmap_cec =devm_regmap_init_i2c (adv7511->i2c_cec, + &adv7533_cec_regmap_config); +if (IS_ERR (adv7511->regmap_cec)) { + ret =PTR_ERR (adv7511->regmap_cec); + goto err_i2c_unregister_cec; + } + +if (adv7511->type ==ADV7533 ) { + ret =regmap_register_patch (adv7511->regmap_cec, + adv7533_cec_fixed_registers, +ARRAY_SIZE (adv7533_cec_fixed_registers)); +if (ret) + goto err_i2c_unregister_cec; + } +if (i2c->irq) {init_waitqueue_head (&adv7511->wq);
@@ -1022,7 +1118,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)IRQF_ONESHOT ,dev_name (dev), adv7511);if (ret) - goto err_i2c_unregister_device; + goto err_i2c_unregister_cec; }/* CEC is unused for now */
@@ -1033,7 +1129,8 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)i2c_set_clientdata (i2c, adv7511); -adv7511_set_link_config (adv7511, &link_config); +if (adv7511->type ==ADV7511 ) +adv7511_set_link_config (adv7511, &link_config); adv7511->bridge.funcs = &adv7511_bridge_funcs; adv7511->bridge.of_node = dev->of_node;
@@ -1041,12 +1138,14 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) ret =drm_bridge_add (&adv7511->bridge);if (ret) {dev_err (dev,"failed to add adv7511 bridge\n" ); - goto err_i2c_unregister_device; + goto err_i2c_unregister_cec; }return 0 ; -err_i2c_unregister_device: +err_i2c_unregister_cec: +i2c_unregister_device (adv7511->i2c_cec); +err_i2c_unregister_edid:i2c_unregister_device (adv7511->i2c_edid);return ret;
@@ -1058,6 +1157,7 @@ static int adv7511_remove(struct i2c_client *i2c)drm_bridge_remove (&adv7511->bridge); +i2c_unregister_device (adv7511->i2c_cec);i2c_unregister_device (adv7511->i2c_edid);kfree (adv7511->edid);
@@ -1066,17 +1166,19 @@ static int adv7511_remove(struct i2c_client *i2c) }static const struct i2c_device_id adv7511_i2c_ids[] = { - {"adv7511" ,0 }, - {"adv7511w" ,0 }, - {"adv7513" ,0 }, + {"adv7511" ,ADV7511 }, + {"adv7511w" ,ADV7511 }, + {"adv7513" ,ADV7511 }, + {"adv7533" ,ADV7533 }, { } };MODULE_DEVICE_TABLE (i2c, adv7511_i2c_ids);static const struct of_device_id adv7511_of_ids[] = { - { .compatible ="adi,adv7511" , }, - { .compatible ="adi,adv7511w" , }, - { .compatible ="adi,adv7513" , }, + { .compatible ="adi,adv7511" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7511w" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7513" , .data = (void *)ADV7511 }, + { .compatible ="adi,adv7533" , .data = (void *)ADV7533 }, { } };MODULE_DEVICE_TABLE (of, adv7511_of_ids);
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v3 4/7 drm/i2c: adv7511: Create a MIPI DSI device
In reply to Archit TanejaIn order to pass DSI specific parameters to the DSI host, we need the driver to create a mipi_dsi_device DSI device that attaches to the host.
Use of_graph helpers to get the DSI host DT node. Create a MIPI DSI device using this host. Finally, attach this device to the DSI host.
Populate DT parameters (number of data lanes for now) that are required for DSI RX to work correctly. Hardcode few other parameters (rgb, embedded_sync) for now.
--- drivers/gpu/drm/i2c/adv7511.c | 130 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 123 insertions(+), 7 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +123 -7
@@ -11,6 +11,7 @@#include <linux/i2c.h> #include <linux/module.h> #include <linux/of_device.h> +#include <linux/of_graph.h> #include <linux/regmap.h> #include <linux/slab.h>
@@ -19,6 +20,7 @@#include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> +#include <drm/drm_mipi_dsi.h> #include "adv7511.h"
@@ -56,6 +58,11 @@ struct adv7511 {struct gpio_desc *gpio_pd; +/* ADV7533 DSI RX related params */ +struct device_node *host_node; +struct mipi_dsi_device *dsi; +u8 num_dsi_lanes; +enum adv7511_type type; };
@@ -392,8 +399,10 @@ static void adv7511_set_link_config(struct adv7511 *adv7511,static void adv7533_dsi_power_on (struct adv7511 *adv) { -/* set number of dsi lanes (hardcoded to 4 for now) */ -regmap_write (adv->regmap_cec,0x1c ,0x4 <<4 ); +struct mipi_dsi_device *dsi = adv->dsi; + +/* set number of dsi lanes */ +regmap_write (adv->regmap_cec,0x1c , dsi->lanes <<4 );/* disable internal timing generator */ regmap_write (adv->regmap_cec,0x27 ,0x0b );/* enable hdmi */
@@ -889,6 +898,51 @@ static void adv7511_bridge_mode_set(struct drm_bridge *bridge,adv7511_mode_set (adv, mode, adj_mode); } +static int adv7533_attach_dsi (struct adv7511 *adv) +{ +struct device *dev = &adv->i2c_main->dev; +struct mipi_dsi_host *host; +struct mipi_dsi_device *dsi; +int ret =0 ; +const struct mipi_dsi_device_info info = { .type ="adv7533" , + .channel =0 , + .node =NULL , + }; + + host =of_find_mipi_dsi_host_by_node (adv->host_node); +if (!host) { +dev_err (dev,"failed to find dsi host\n" ); +return -EPROBE_DEFER ; + } + + dsi =mipi_dsi_device_register_full (host, &info); +if (IS_ERR (dsi)) { +dev_err (dev,"failed to create dsi device\n" ); + ret =PTR_ERR (dsi); + goto err_dsi_device; + } + + adv->dsi = dsi; + + dsi->lanes = adv->num_dsi_lanes; + dsi->format =MIPI_DSI_FMT_RGB888 ; + dsi->mode_flags =MIPI_DSI_MODE_VIDEO |MIPI_DSI_MODE_VIDEO_SYNC_PULSE | +MIPI_DSI_MODE_EOT_PACKET |MIPI_DSI_MODE_VIDEO_HSE ; + + ret =mipi_dsi_attach (dsi); +if (ret <0 ) { +dev_err (dev,"failed to attach dsi to host\n" ); + goto err_dsi_attach; + } + +return 0 ; + +err_dsi_attach: +mipi_dsi_device_unregister (dsi); +err_dsi_device: +return ret; +} +static int adv7511_bridge_attach (struct drm_bridge *bridge) {struct adv7511 *adv =bridge_to_adv7511 (bridge);
@@ -912,6 +966,9 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) &adv7511_connector_helper_funcs);drm_mode_connector_attach_encoder (&adv->connector, bridge->encoder); +if (adv->type ==ADV7533 ) + ret =adv7533_attach_dsi (adv); +return ret; }
@@ -1009,6 +1066,41 @@ static int adv7511_parse_dt(struct device_node *np,return 0 ; } +static int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv) +{ +u32 num_lanes; +struct device_node *endpoint; + +of_property_read_u32 (np,"adi,dsi-lanes" , &num_lanes); + +if (num_lanes <1 || num_lanes >4 ) +return -EINVAL ; + + adv->num_dsi_lanes = num_lanes; + + endpoint =of_graph_get_next_endpoint (np,NULL ); +if (!endpoint) { +DRM_ERROR ("ADV7533 DSI input endpoint not found\n" ); +return -ENODEV ; + } + + adv->host_node =of_graph_get_remote_port_parent (endpoint); +if (!adv->host_node) { +DRM_ERROR ("DSI host node not found\n" ); +of_node_put (endpoint); +return -ENODEV ; + } + +of_node_put (endpoint); +of_node_put (adv->host_node); + +/* TODO: Check if these need to be parsed by DT or not */ + adv->rgb = true; + adv->embedded_sync = false; + +return 0 ; +} +static const int edid_i2c_addr =0x7e ;static const int packet_i2c_addr =0x70 ;static const int cec_i2c_addr =0x78 ;
@@ -1038,11 +1130,12 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)memset (&link_config,0 ,sizeof (link_config)); -if (adv7511->type ==ADV7511 ) { +if (adv7511->type ==ADV7511 ) ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; - } +else + ret =adv7533_parse_dt (dev->of_node, adv7511); +if (ret) +return ret;/* * The power down GPIO is optional. If present, toggle it from active to
@@ -1155,6 +1248,11 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +if (adv7511->type ==ADV7533 ) { +mipi_dsi_detach (adv7511->dsi); +mipi_dsi_device_unregister (adv7511->dsi); + } +drm_bridge_remove (&adv7511->bridge);i2c_unregister_device (adv7511->i2c_cec);
@@ -1183,6 +1281,10 @@ static const struct of_device_id adv7511_of_ids[] = { };MODULE_DEVICE_TABLE (of, adv7511_of_ids); +static struct mipi_dsi_driver adv7533_dsi_driver = { + .driver.name ="adv7533" , +}; +static struct i2c_driver adv7511_driver = { .driver = { .name ="adv7511" ,
@@ -1193,7 +1295,21 @@ static struct i2c_driver adv7511_driver = { .remove = adv7511_remove, }; -module_i2c_driver (adv7511_driver); +static int __init adv7511_init (void ) +{ +mipi_dsi_driver_register (&adv7533_dsi_driver); + +return i2c_add_driver (&adv7511_driver); +} +module_init (adv7511_init); + +static void __exit adv7511_exit(void) +{ +i2c_del_driver (&adv7511_driver); + +mipi_dsi_driver_unregister (&adv7533_dsi_driver); +} +module_exit (adv7511_exit);MODULE_AUTHOR ("Lars-Peter Clausen <[email protected]>" );MODULE_DESCRIPTION ("ADV7511 HDMI transmitter driver" );
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Laurent Pinchart
reviewerRe: [PATCH v3 4/7] drm/i2c: adv7511: Create a MIPI DSI device
Hi Archit,
Thank you for the patch.
Quoted 4 lines · On Wednesday 09 Mar 2016 16:27:15 Archit Taneja wrote:
In order to pass DSI specific parameters to the DSI host, we need the driver to create a
mipi_dsi_deviceDSI device that attaches to the host.
Quoted 8 lines
Use
of_graphhelpers to get the DSI host DT node. Create a MIPI DSI device using this host. Finally, attach this device to the DSI host.Populate DT parameters (number of data lanes for now) that are required for DSI RX to work correctly. Hardcode few other parameters (rgb,
embedded_sync) for now.Signed-off-by Archit Taneja <[email protected]>
This adds a hard dependency on CONFIG_DRM_MIPI_DSI, otherwise the kernel won't link. As the ADV7511 doesn't require DSI, could you make it optional with conditional compilation to avoid pulling in dead code ?
Quoted 218 lines
--- drivers/gpu/drm/i2c/adv7511.c | 130 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 123 insertions(+), 7 deletions(-)drivers/gpu/drm/i2c/adv7511.c +11
-2@@ -11,6 +11,7 @@#include <linux/i2c.h> #include <linux/module.h> #include <linux/of_device.h> +#include <linux/of_graph.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -19,6 +20,7 @@#include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> +#include <drm/drm_mipi_dsi.h> #include "adv7511.h" @@ -56,6 +58,11 @@ struct adv7511 {struct gpio_desc *gpio_pd; +/* ADV7533 DSI RX related params */ +struct device_node *host_node; +struct mipi_dsi_device *dsi; +u8 num_dsi_lanes; +enum adv7511_type type; };@@ -392,8 +399,10 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, static void adv7533_dsi_power_on(struct adv7511 *adv) { -/* set number of dsi lanes (hardcoded to 4 for now) */ -regmap_write (adv->regmap_cec,0x1c ,0x4 <<4 ); +struct mipi_dsi_device *dsi = adv->dsi; + +/* set number of dsi lanes */ +regmap_write (adv->regmap_cec,0x1c , dsi->lanes <<4 );/* disable internal timing generator */ regmap_write (adv->regmap_cec,0x27 ,0x0b );drivers/gpu/drm/i2c/adv7511.c +88
-4/* enable hdmi */ @@ -889,6 +898,51 @@ static void adv7511_bridge_mode_set(struct drm_bridge *bridge,adv7511_mode_set (adv, mode, adj_mode); } +static int adv7533_attach_dsi (struct adv7511 *adv) +{ +struct device *dev = &adv->i2c_main->dev; +struct mipi_dsi_host *host; +struct mipi_dsi_device *dsi; +int ret =0 ; +const struct mipi_dsi_device_info info = { .type ="adv7533" , + .channel =0 , + .node =NULL , + }; + + host =of_find_mipi_dsi_host_by_node (adv->host_node); +if (!host) { +dev_err (dev,"failed to find dsi host\n" ); +return -EPROBE_DEFER ; + } + + dsi =mipi_dsi_device_register_full (host, &info); +if (IS_ERR (dsi)) { +dev_err (dev,"failed to create dsi device\n" ); + ret =PTR_ERR (dsi); + goto err_dsi_device; + } + + adv->dsi = dsi; + + dsi->lanes = adv->num_dsi_lanes; + dsi->format =MIPI_DSI_FMT_RGB888 ; + dsi->mode_flags =MIPI_DSI_MODE_VIDEO |MIPI_DSI_MODE_VIDEO_SYNC_PULSE | +MIPI_DSI_MODE_EOT_PACKET |MIPI_DSI_MODE_VIDEO_HSE ; + + ret =mipi_dsi_attach (dsi); +if (ret <0 ) { +dev_err (dev,"failed to attach dsi to host\n" ); + goto err_dsi_attach; + } + +return 0 ; + +err_dsi_attach: +mipi_dsi_device_unregister (dsi); +err_dsi_device: +return ret; +} +static int adv7511_bridge_attach (struct drm_bridge *bridge) {struct adv7511 *adv =bridge_to_adv7511 (bridge);@@ -912,6 +966,9 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) &adv7511_connector_helper_funcs);drm_mode_connector_attach_encoder (&adv->connector, bridge->encoder); +if (adv->type ==ADV7533 ) + ret =adv7533_attach_dsi (adv); +return ret; }@@ -1009,6 +1066,41 @@ static int adv7511_parse_dt(struct device_node *np,return 0 ; } +static int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv) +{ +u32 num_lanes; +struct device_node *endpoint; + +of_property_read_u32 (np,"adi,dsi-lanes" , &num_lanes); + +if (num_lanes <1 || num_lanes >4 ) +return -EINVAL ; + + adv->num_dsi_lanes = num_lanes; + + endpoint =of_graph_get_next_endpoint (np,NULL ); +if (!endpoint) { +DRM_ERROR ("ADV7533 DSI input endpoint not found\n" ); +return -ENODEV ; + } + + adv->host_node =of_graph_get_remote_port_parent (endpoint); +if (!adv->host_node) { +DRM_ERROR ("DSI host node not found\n" ); +of_node_put (endpoint); +return -ENODEV ; + } + +of_node_put (endpoint); +of_node_put (adv->host_node); + +/* TODO: Check if these need to be parsed by DT or not */ + adv->rgb = true; + adv->embedded_sync = false; + +return 0 ; +} +static const int edid_i2c_addr =0x7e ;static const int packet_i2c_addr =0x70 ;static const int cec_i2c_addr =0x78 ;@@ -1038,11 +1130,12 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) memset(&link_config, 0, sizeof(link_config)); -if (adv7511->type ==ADV7511 ) { +if (adv7511->type ==ADV7511 ) ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; - } +else + ret =adv7533_parse_dt (dev->of_node, adv7511); +if (ret) +return ret;/* drivers/gpu/drm/i2c/adv7511.c +24
-1* The power down GPIO is optional. If present, toggle it from active to @@ -1155,6 +1248,11 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +if (adv7511->type ==ADV7533 ) { +mipi_dsi_detach (adv7511->dsi); +mipi_dsi_device_unregister (adv7511->dsi); + } +drm_bridge_remove (&adv7511->bridge);i2c_unregister_device (adv7511->i2c_cec);@@ -1183,6 +1281,10 @@ static const struct of_device_id adv7511_of_ids[] = { };MODULE_DEVICE_TABLE (of, adv7511_of_ids); +static struct mipi_dsi_driver adv7533_dsi_driver = { + .driver.name ="adv7533" , +}; +static struct i2c_driver adv7511_driver = { .driver = { .name ="adv7511" ,@@ -1193,7 +1295,21 @@ static struct i2c_driver adv7511_driver = { .remove = adv7511_remove, }; -module_i2c_driver (adv7511_driver); +static int __init adv7511_init (void ) +{ +mipi_dsi_driver_register (&adv7533_dsi_driver); + +return i2c_add_driver (&adv7511_driver); +} +module_init (adv7511_init); + +static void __exit adv7511_exit(void) +{ +i2c_del_driver (&adv7511_driver); + +mipi_dsi_driver_unregister (&adv7533_dsi_driver); +} +module_exit (adv7511_exit);MODULE_AUTHOR ("Lars-Peter Clausen <[email protected]>" );MODULE_DESCRIPTION ("ADV7511 HDMI transmitter driver" );
Signature · 8 lines
Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 4/7] drm/i2c: adv7511: Create a MIPI DSI device
Hi Laurent,
Quoted 16 lines · Laurent Pinchart
Hi Archit,
Thank you for the patch.
Quoted 11 lines · On Wednesday 09 Mar 2016 16:27:15 Archit Taneja wrote:
In order to pass DSI specific parameters to the DSI host, we need the driver to create a
mipi_dsi_deviceDSI device that attaches to the host.Use
of_graphhelpers to get the DSI host DT node. Create a MIPI DSI device using this host. Finally, attach this device to the DSI host.Populate DT parameters (number of data lanes for now) that are required for DSI RX to work correctly. Hardcode few other parameters (rgb,
embedded_sync) for now.
Quoted 5 lines
Quoted 1 line
Signed-off-by Archit Taneja <[email protected]>This adds a hard dependency on
CONFIG_DRM_MIPI_DSI, otherwise the kernel won't link. As the ADV7511 doesn't require DSI, could you make it optional with conditional compilation to avoid pulling in dead code ?
You're right. The driver's Kconfig should at least select DRM_MIPI_DSI in the current state to make sure we don't break build.
Do you suggest we create another config option for ADV7533, which selects DRM_MIPI_DSI and builds the ADV7533 parts? Or did you mean something else?
Thanks for the review.
Archit
Quoted 220 lines
Quoted 219 lines
--- drivers/gpu/drm/i2c/adv7511.c | 130 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 123 insertions(+), 7 deletions(-)drivers/gpu/drm/i2c/adv7511.c +11
-2@@ -11,6 +11,7 @@#include <linux/i2c.h> #include <linux/module.h> #include <linux/of_device.h> +#include <linux/of_graph.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -19,6 +20,7 @@#include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> +#include <drm/drm_mipi_dsi.h> #include "adv7511.h" @@ -56,6 +58,11 @@ struct adv7511 {struct gpio_desc *gpio_pd; +/* ADV7533 DSI RX related params */ +struct device_node *host_node; +struct mipi_dsi_device *dsi; +u8 num_dsi_lanes; +enum adv7511_type type; };@@ -392,8 +399,10 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, static void adv7533_dsi_power_on(struct adv7511 *adv) { -/* set number of dsi lanes (hardcoded to 4 for now) */ -regmap_write (adv->regmap_cec,0x1c ,0x4 <<4 ); +struct mipi_dsi_device *dsi = adv->dsi; + +/* set number of dsi lanes */ +regmap_write (adv->regmap_cec,0x1c , dsi->lanes <<4 );/* disable internal timing generator */ regmap_write (adv->regmap_cec,0x27 ,0x0b );/* enable hdmi */
drivers/gpu/drm/i2c/adv7511.c +88
-4@@ -889,6 +898,51 @@ static void adv7511_bridge_mode_set(struct drm_bridge *bridge,adv7511_mode_set (adv, mode, adj_mode); } +static int adv7533_attach_dsi (struct adv7511 *adv) +{ +struct device *dev = &adv->i2c_main->dev; +struct mipi_dsi_host *host; +struct mipi_dsi_device *dsi; +int ret =0 ; +const struct mipi_dsi_device_info info = { .type ="adv7533" , + .channel =0 , + .node =NULL , + }; + + host =of_find_mipi_dsi_host_by_node (adv->host_node); +if (!host) { +dev_err (dev,"failed to find dsi host\n" ); +return -EPROBE_DEFER ; + } + + dsi =mipi_dsi_device_register_full (host, &info); +if (IS_ERR (dsi)) { +dev_err (dev,"failed to create dsi device\n" ); + ret =PTR_ERR (dsi); + goto err_dsi_device; + } + + adv->dsi = dsi; + + dsi->lanes = adv->num_dsi_lanes; + dsi->format =MIPI_DSI_FMT_RGB888 ; + dsi->mode_flags =MIPI_DSI_MODE_VIDEO |MIPI_DSI_MODE_VIDEO_SYNC_PULSE | +MIPI_DSI_MODE_EOT_PACKET |MIPI_DSI_MODE_VIDEO_HSE ; + + ret =mipi_dsi_attach (dsi); +if (ret <0 ) { +dev_err (dev,"failed to attach dsi to host\n" ); + goto err_dsi_attach; + } + +return 0 ; + +err_dsi_attach: +mipi_dsi_device_unregister (dsi); +err_dsi_device: +return ret; +} +static int adv7511_bridge_attach (struct drm_bridge *bridge) {struct adv7511 *adv =bridge_to_adv7511 (bridge);@@ -912,6 +966,9 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) &adv7511_connector_helper_funcs);drm_mode_connector_attach_encoder (&adv->connector, bridge->encoder); +if (adv->type ==ADV7533 ) + ret =adv7533_attach_dsi (adv); +return ret; }@@ -1009,6 +1066,41 @@ static int adv7511_parse_dt(struct device_node *np,return 0 ; } +static int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv) +{ +u32 num_lanes; +struct device_node *endpoint; + +of_property_read_u32 (np,"adi,dsi-lanes" , &num_lanes); + +if (num_lanes <1 || num_lanes >4 ) +return -EINVAL ; + + adv->num_dsi_lanes = num_lanes; + + endpoint =of_graph_get_next_endpoint (np,NULL ); +if (!endpoint) { +DRM_ERROR ("ADV7533 DSI input endpoint not found\n" ); +return -ENODEV ; + } + + adv->host_node =of_graph_get_remote_port_parent (endpoint); +if (!adv->host_node) { +DRM_ERROR ("DSI host node not found\n" ); +of_node_put (endpoint); +return -ENODEV ; + } + +of_node_put (endpoint); +of_node_put (adv->host_node); + +/* TODO: Check if these need to be parsed by DT or not */ + adv->rgb = true; + adv->embedded_sync = false; + +return 0 ; +} +static const int edid_i2c_addr =0x7e ;static const int packet_i2c_addr =0x70 ;static const int cec_i2c_addr =0x78 ;@@ -1038,11 +1130,12 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) memset(&link_config, 0, sizeof(link_config)); -if (adv7511->type ==ADV7511 ) { +if (adv7511->type ==ADV7511 ) ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; - } +else + ret =adv7533_parse_dt (dev->of_node, adv7511); +if (ret) +return ret;/* * The power down GPIO is optional. If present, toggle it from active to
drivers/gpu/drm/i2c/adv7511.c +24
-1@@ -1155,6 +1248,11 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +if (adv7511->type ==ADV7533 ) { +mipi_dsi_detach (adv7511->dsi); +mipi_dsi_device_unregister (adv7511->dsi); + } +drm_bridge_remove (&adv7511->bridge);i2c_unregister_device (adv7511->i2c_cec);@@ -1183,6 +1281,10 @@ static const struct of_device_id adv7511_of_ids[] = { };MODULE_DEVICE_TABLE (of, adv7511_of_ids); +static struct mipi_dsi_driver adv7533_dsi_driver = { + .driver.name ="adv7533" , +}; +static struct i2c_driver adv7511_driver = { .driver = { .name ="adv7511" ,@@ -1193,7 +1295,21 @@ static struct i2c_driver adv7511_driver = { .remove = adv7511_remove, }; -module_i2c_driver (adv7511_driver); +static int __init adv7511_init (void ) +{ +mipi_dsi_driver_register (&adv7533_dsi_driver); + +return i2c_add_driver (&adv7511_driver); +} +module_init (adv7511_init); + +static void __exit adv7511_exit(void) +{ +i2c_del_driver (&adv7511_driver); + +mipi_dsi_driver_unregister (&adv7533_dsi_driver); +} +module_exit (adv7511_exit);MODULE_AUTHOR ("Lars-Peter Clausen <[email protected]>" );MODULE_DESCRIPTION ("ADV7511 HDMI transmitter driver" );
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v3 4/7] drm/i2c: adv7511: Create a MIPI DSI device
Hi Laurent,
Quoted 27 lines · Archit Taneja
Hi Laurent,
Quoted 16 lines · Laurent Pinchart
Hi Archit,
Thank you for the patch.
Quoted 11 lines · On Wednesday 09 Mar 2016 16:27:15 Archit Taneja wrote:
In order to pass DSI specific parameters to the DSI host, we need the driver to create a
mipi_dsi_deviceDSI device that attaches to the host.Use
of_graphhelpers to get the DSI host DT node. Create a MIPI DSI device using this host. Finally, attach this device to the DSI host.Populate DT parameters (number of data lanes for now) that are required for DSI RX to work correctly. Hardcode few other parameters (rgb,
embedded_sync) for now.Quoted 6 lines
Quoted 1 line
Signed-off-by Archit Taneja <[email protected]>This adds a hard dependency on
CONFIG_DRM_MIPI_DSI, otherwise the kernel won't
link. As the ADV7511 doesn't require DSI, could you make it optional with conditional compilation to avoid pulling in dead code ?
Quoted 6 lines
You're right. The driver's
Kconfigshould at least selectDRM_MIPI_DSIin the current state to make sure we don't break build.Do you suggest we create another config option for ADV7533, which selects
DRM_MIPI_DSIand builds the ADV7533 parts? Or did you mean something else?
Do you have any suggestions for this point? For the next revision, I've just selected DRM_MIPI_DSI in the Kconfig to ensure build doesn't break.
For this driver, to conditionally compile DRM_MIPI_DSI, it essentially means we allow conditional support for ADV7533. I would imagine us #ifdef-ing out the ADV7533 compatible string in the of_match_table. Is this something we want to do?
Thanks,
Archit
Quoted 231 lines
Quoted 230 lines
Quoted 229 lines
--- drivers/gpu/drm/i2c/adv7511.c | 130 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 123 insertions(+), 7 deletions(-)drivers/gpu/drm/i2c/adv7511.c +11
-2@@ -11,6 +11,7 @@#include <linux/i2c.h> #include <linux/module.h> #include <linux/of_device.h> +#include <linux/of_graph.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -19,6 +20,7 @@#include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> +#include <drm/drm_mipi_dsi.h> #include "adv7511.h" @@ -56,6 +58,11 @@ struct adv7511 {struct gpio_desc *gpio_pd; +/* ADV7533 DSI RX related params */ +struct device_node *host_node; +struct mipi_dsi_device *dsi; +u8 num_dsi_lanes; +enum adv7511_type type; };@@ -392,8 +399,10 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, static void adv7533_dsi_power_on(struct adv7511 *adv) { -/* set number of dsi lanes (hardcoded to 4 for now) */ -regmap_write (adv->regmap_cec,0x1c ,0x4 <<4 ); +struct mipi_dsi_device *dsi = adv->dsi; + +/* set number of dsi lanes */ +regmap_write (adv->regmap_cec,0x1c , dsi->lanes <<4 );/* disable internal timing generator */ regmap_write (adv->regmap_cec,0x27 ,0x0b );/* enable hdmi */drivers/gpu/drm/i2c/adv7511.c +0
-0@@ -889,6 +898,51 @@ static void adv7511_bridge_mode_set(struct
drm_bridge
*bridge,adv7511_mode_set(adv, mode, adj_mode);
}drivers/gpu/drm/i2c/adv7511.c +29
-0+static int adv7533_attach_dsi (struct adv7511 *adv) +{ +struct device *dev = &adv->i2c_main->dev; +struct mipi_dsi_host *host; +struct mipi_dsi_device *dsi; +int ret =0 ; +const struct mipi_dsi_device_info info = { .type ="adv7533" , + .channel =0 , + .node =NULL , + }; + + host =of_find_mipi_dsi_host_by_node (adv->host_node); +if (!host) { +dev_err (dev,"failed to find dsi host\n" ); +return -EPROBE_DEFER ; + } + + dsi =mipi_dsi_device_register_full (host, &info); +if (IS_ERR (dsi)) { +dev_err (dev,"failed to create dsi device\n" ); + ret =PTR_ERR (dsi); + goto err_dsi_device; + } + + adv->dsi = dsi; + + dsi->lanes = adv->num_dsi_lanes; + dsi->format =MIPI_DSI_FMT_RGB888 ; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_SYNC_PULSE|drivers/gpu/drm/i2c/adv7511.c +54
-0+MIPI_DSI_MODE_EOT_PACKET |MIPI_DSI_MODE_VIDEO_HSE ; + + ret =mipi_dsi_attach (dsi); +if (ret <0 ) { +dev_err (dev,"failed to attach dsi to host\n" ); + goto err_dsi_attach; + } + +return 0 ; + +err_dsi_attach: +mipi_dsi_device_unregister (dsi); +err_dsi_device: +return ret; +} +static int adv7511_bridge_attach (struct drm_bridge *bridge) {struct adv7511 *adv =bridge_to_adv7511 (bridge);@@ -912,6 +966,9 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) &adv7511_connector_helper_funcs);drm_mode_connector_attach_encoder (&adv->connector, bridge->encoder); +if (adv->type ==ADV7533 ) + ret =adv7533_attach_dsi (adv); +return ret; }@@ -1009,6 +1066,41 @@ static int adv7511_parse_dt(struct device_node *np, return 0; } +static int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv) +{ +u32 num_lanes; +struct device_node *endpoint; + +of_property_read_u32 (np,"adi,dsi-lanes" , &num_lanes); + +if (num_lanes <1 || num_lanes >4 ) +return -EINVAL ; + + adv->num_dsi_lanes = num_lanes; + + endpoint =of_graph_get_next_endpoint (np,NULL ); +if (!endpoint) { +DRM_ERROR ("ADV7533 DSI input endpoint not found\n" ); +return -ENODEV ; + } + + adv->host_node =of_graph_get_remote_port_parent (endpoint); +if (!adv->host_node) { +DRM_ERROR ("DSI host node not found\n" ); +of_node_put (endpoint); +return -ENODEV ; + } + +of_node_put (endpoint); +of_node_put (adv->host_node); + +/* TODO: Check if these need to be parsed by DT or not */ + adv->rgb = true; + adv->embedded_sync = false; + +return 0 ; +} +static const int edid_i2c_addr =0x7e ;static const int packet_i2c_addr = 0x70; static const int cec_i2c_addr = 0x78;drivers/gpu/drm/i2c/adv7511.c +5
-4@@ -1038,11 +1130,12 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) memset(&link_config, 0, sizeof(link_config)); -if (adv7511->type ==ADV7511 ) { +if (adv7511->type ==ADV7511 ) ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; - } +else + ret =adv7533_parse_dt (dev->of_node, adv7511); +if (ret) +return ret;/* * The power down GPIO is optional. If present, toggle it from
active todrivers/gpu/drm/i2c/adv7511.c +9
-0@@ -1155,6 +1248,11 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +if (adv7511->type ==ADV7533 ) { +mipi_dsi_detach (adv7511->dsi); +mipi_dsi_device_unregister (adv7511->dsi); + } +drm_bridge_remove (&adv7511->bridge);i2c_unregister_device (adv7511->i2c_cec);@@ -1183,6 +1281,10 @@ static const struct of_device_id adv7511_of_ids[] = { };MODULE_DEVICE_TABLE (of, adv7511_of_ids); +static struct mipi_dsi_driver adv7533_dsi_driver = { + .driver.name ="adv7533" , +}; +static struct i2c_driver adv7511_driver = { .driver = {.name = "adv7511",drivers/gpu/drm/i2c/adv7511.c +15
-1@@ -1193,7 +1295,21 @@ static struct i2c_driver adv7511_driver = { .remove = adv7511_remove, }; -module_i2c_driver (adv7511_driver); +static int __init adv7511_init (void ) +{ +mipi_dsi_driver_register (&adv7533_dsi_driver); + +return i2c_add_driver (&adv7511_driver); +} +module_init (adv7511_init); + +static void __exit adv7511_exit(void) +{ +i2c_del_driver (&adv7511_driver); + +mipi_dsi_driver_unregister (&adv7533_dsi_driver); +} +module_exit (adv7511_exit);MODULE_AUTHOR ("Lars-Peter Clausen <[email protected]>" );MODULE_DESCRIPTION ("ADV7511 HDMI transmitter driver" );
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Laurent Pinchart
reviewerRe: [PATCH v3 4/7] drm/i2c: adv7511: Create a MIPI DSI device
Hi Archit,
Quoted 27 lines · On Tuesday 03 May 2016 12:27:38 Archit Taneja wrote:
Quoted 19 lines · Archit Taneja
Quoted 12 lines · Laurent Pinchart
Quoted 11 lines · On Wednesday 09 Mar 2016 16:27:15 Archit Taneja wrote:
In order to pass DSI specific parameters to the DSI host, we need the driver to create a
mipi_dsi_deviceDSI device that attaches to the host.Use
of_graphhelpers to get the DSI host DT node. Create a MIPI DSI device using this host. Finally, attach this device to the DSI host.Populate DT parameters (number of data lanes for now) that are required for DSI RX to work correctly. Hardcode few other parameters (rgb,
embedded_sync) for now.Quoted 5 lines
Quoted 1 line
Signed-off-by Archit Taneja <[email protected]>This adds a hard dependency on
CONFIG_DRM_MIPI_DSI, otherwise the kernel won't link. As the ADV7511 doesn't require DSI, could you make it optional with conditional compilation to avoid pulling in dead code ?Quoted 6 lines
You're right. The driver's
Kconfigshould at least selectDRM_MIPI_DSIin the current state to make sure we don't break build.Do you suggest we create another config option for ADV7533, which selects
DRM_MIPI_DSIand builds the ADV7533 parts? Or did you mean something else?
Quoted 7 lines
Do you have any suggestions for this point? For the next revision, I've just selected
DRM_MIPI_DSIin theKconfigto ensure build doesn't break.For this driver, to conditionally compile
DRM_MIPI_DSI, it essentially means we allow conditional support for ADV7533. I would imagine us #ifdef-ing out the ADV7533 compatible string in theof_match_table. Is this something we want to do?
If it's not much trouble I think that would be useful to avoid bloating the kernel with unused features, yes. You might want to add stub functions to include/drm/drm_mipi_dsi.h when CONFIG_DRM_MIPI_DSI is not defined to avoid sprinkling the driver with lots of #ifdefs.
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
---
drivers/gpu/drm/i2c/adv7511.c| 130 +++++++++++++++++++++++++++++++++---1 file changed, 123 insertions(+), 7 deletions(-)
Signature · 3 lines
Regards, Laurent Pinchart
Re: [PATCH v3 4/7] drm/i2c: adv7511: Create a MIPI DSI device
Quoted 38 lines · Laurent Pinchart
Hi Archit,
Quoted 27 lines · On Tuesday 03 May 2016 12:27:38 Archit Taneja wrote:
Quoted 19 lines · Archit Taneja
Quoted 12 lines · Laurent Pinchart
Quoted 11 lines · On Wednesday 09 Mar 2016 16:27:15 Archit Taneja wrote:
In order to pass DSI specific parameters to the DSI host, we need the driver to create a
mipi_dsi_deviceDSI device that attaches to the host.Use
of_graphhelpers to get the DSI host DT node. Create a MIPI DSI device using this host. Finally, attach this device to the DSI host.Populate DT parameters (number of data lanes for now) that are required for DSI RX to work correctly. Hardcode few other parameters (rgb,
embedded_sync) for now.Quoted 5 lines
Quoted 1 line
Signed-off-by Archit Taneja <[email protected]>This adds a hard dependency on
CONFIG_DRM_MIPI_DSI, otherwise the kernel won't link. As the ADV7511 doesn't require DSI, could you make it optional with conditional compilation to avoid pulling in dead code ?Quoted 6 lines
You're right. The driver's
Kconfigshould at least selectDRM_MIPI_DSIin the current state to make sure we don't break build.Do you suggest we create another config option for ADV7533, which selects
DRM_MIPI_DSIand builds the ADV7533 parts? Or did you mean something else?Quoted 7 lines
Do you have any suggestions for this point? For the next revision, I've just selected
DRM_MIPI_DSIin theKconfigto ensure build doesn't break.For this driver, to conditionally compile
DRM_MIPI_DSI, it essentially means we allow conditional support for ADV7533. I would imagine us #ifdef-ing out the ADV7533 compatible string in theof_match_table. Is this something we want to do?
Quoted 4 lines
If it's not much trouble I think that would be useful to avoid bloating the kernel with unused features, yes. You might want to add stub functions to
include/drm/drm_mipi_dsi.hwhenCONFIG_DRM_MIPI_DSIis not defined to avoid sprinkling the driver with lots of #ifdefs.
Yeah, I can do this. Now that there isn't a chance for it to get in the 4.7 merge window, there's plenty time.
Archit
Quoted 6 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
---
drivers/gpu/drm/i2c/adv7511.c| 130 +++++++++++++++++++++++++++++++++---1 file changed, 123 insertions(+), 7 deletions(-)
Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v3 5/7 drm/i2c: adv7511: Use internal timing generator
In reply to Archit TanejaADV7533 provides an internal timing generator for certain modes that it can't use the DSI clock directly.
We've observed that HDMI is more stable with the internal timing generator, especially if there are instabilities in the DSI clock source. The data spec also seems to recommend the usage of the timing generator for all modes.
However, on some platforms, it's reported that enabling the timing generator causes instabilities with the HDMI output.
Create a DT parameter that lets a platform explicitly disable the timing generator. The timing generator is enabled by default.
--- drivers/gpu/drm/i2c/adv7511.c | 65 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +63 -2
@@ -39,6 +39,8 @@ struct adv7511 {enum drm_connector_status status;bool powered; +struct drm_display_mode curr_mode; +unsigned int f_tmds;unsigned int current_edid_segment;
@@ -62,6 +64,7 @@ struct adv7511 {struct device_node *host_node;struct mipi_dsi_device *dsi;u8 num_dsi_lanes; +bool use_timing_gen;enum adv7511_type type; };
@@ -397,14 +400,65 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, adv7511->rgb = config->input_colorspace ==HDMI_COLORSPACE_RGB ; } +static void adv7511_dsi_config_timing_gen (struct adv7511 *adv) +{ +struct mipi_dsi_device *dsi = adv->dsi; +struct drm_display_mode *mode = &adv->curr_mode; +unsigned int hsw, hfp, hbp, vsw, vfp, vbp; +u8 clock_div_by_lanes[] = {6 ,4 ,3 };/* 2, 3, 4 lanes */ + + hsw = mode->hsync_end - mode->hsync_start; + hfp = mode->hsync_start - mode->hdisplay; + hbp = mode->htotal - mode->hsync_end; + vsw = mode->vsync_end - mode->vsync_start; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + +/* set pixel clock divider mode */ +regmap_write (adv->regmap_cec,0x16 , + clock_div_by_lanes[dsi->lanes -2 ] <<3 ); + +/* horizontal porch params */ +regmap_write (adv->regmap_cec,0x28 , mode->htotal >>4 ); +regmap_write (adv->regmap_cec,0x29 , (mode->htotal <<4 ) &0xff ); +regmap_write (adv->regmap_cec,0x2a , hsw >>4 ); +regmap_write (adv->regmap_cec,0x2b , (hsw <<4 ) &0xff ); +regmap_write (adv->regmap_cec,0x2c , hfp >>4 ); +regmap_write (adv->regmap_cec,0x2d , (hfp <<4 ) &0xff ); +regmap_write (adv->regmap_cec,0x2e , hbp >>4 ); +regmap_write (adv->regmap_cec,0x2f , (hbp <<4 ) &0xff ); + +/* vertical porch params */ +regmap_write (adv->regmap_cec,0x30 , mode->vtotal >>4 ); +regmap_write (adv->regmap_cec,0x31 , (mode->vtotal <<4 ) &0xff ); +regmap_write (adv->regmap_cec,0x32 , vsw >>4 ); +regmap_write (adv->regmap_cec,0x33 , (vsw <<4 ) &0xff ); +regmap_write (adv->regmap_cec,0x34 , vfp >>4 ); +regmap_write (adv->regmap_cec,0x35 , (vfp <<4 ) &0xff ); +regmap_write (adv->regmap_cec,0x36 , vbp >>4 ); +regmap_write (adv->regmap_cec,0x37 , (vbp <<4 ) &0xff ); +} +static void adv7533_dsi_power_on (struct adv7511 *adv) {struct mipi_dsi_device *dsi = adv->dsi; +if (adv->use_timing_gen) +adv7511_dsi_config_timing_gen (adv); +/* set number of dsi lanes */ regmap_write (adv->regmap_cec,0x1c , dsi->lanes <<4 ); -/* disable internal timing generator */ -regmap_write (adv->regmap_cec,0x27 ,0x0b ); + +if (adv->use_timing_gen) { +/* reset internal timing generator */ +regmap_write (adv->regmap_cec,0x27 ,0xcb ); +regmap_write (adv->regmap_cec,0x27 ,0x8b ); +regmap_write (adv->regmap_cec,0x27 ,0xcb ); + }else { +/* disable internal timing generator */ +regmap_write (adv->regmap_cec,0x27 ,0x0b ); + } +/* enable hdmi */ regmap_write (adv->regmap_cec,0x03 ,0x89 );/* disable test mode */
@@ -459,6 +513,8 @@ static void adv7533_dsi_power_off(struct adv7511 *adv) {/* disable hdmi */ regmap_write (adv->regmap_cec,0x03 ,0x0b ); +/* disable internal timing generator */ +regmap_write (adv->regmap_cec,0x27 ,0x0b ); }static void adv7511_power_off (struct adv7511 *adv7511)
@@ -807,6 +863,8 @@ static void adv7511_mode_set(struct adv7511 *adv7511,regmap_update_bits (adv7511->regmap,0x17 ,0x60 , (vsync_polarity <<6 ) | (hsync_polarity <<5 )); +drm_mode_copy (&adv7511->curr_mode, adj_mode); +/* * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is * supposed to give better results.
@@ -1094,6 +1152,9 @@ static int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)of_node_put (endpoint);of_node_put (adv->host_node); + adv->use_timing_gen = !of_property_read_bool (np, +"adi,disable-timing-generator" ); +/* TODO: Check if these need to be parsed by DT or not */ adv->rgb = true; adv->embedded_sync = false;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v3 6/7 drm/i2c: adv7511: Change number of DSI lanes dynamically
In reply to Archit TanejaLower modes on ADV7533 require lower number of DSI lanes for correct operation. If ADV7533 is being used with 4 DSI lanes, then switch the lanes to 3 when the target mode's pixel clock is less than 80 Mhz.
Based on patch by Andy Green <[email protected]>
--- drivers/gpu/drm/i2c/adv7511.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
drivers/gpu/drm/i2c/adv7511.c +20 -0
@@ -863,6 +863,26 @@ static void adv7511_mode_set(struct adv7511 *adv7511,regmap_update_bits (adv7511->regmap,0x17 ,0x60 , (vsync_polarity <<6 ) | (hsync_polarity <<5 )); +if (adv7511->type ==ADV7533 && adv7511->num_dsi_lanes ==4 ) { +struct mipi_dsi_device *dsi = adv7511->dsi; +int lanes, ret; + +if (adj_mode->clock >80000 ) + lanes =4 ; +else + lanes =3 ; + +if (lanes != dsi->lanes) { +mipi_dsi_detach (dsi); + dsi->lanes = lanes; + ret =mipi_dsi_attach (dsi); +if (ret) { +DRM_ERROR ("Failed to change host lanes\n" ); +return ; + } + } + } +drm_mode_copy (&adv7511->curr_mode, adj_mode);/*
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
A message that is not in the archive (sent off-list or not yet received): 1457521038-5906-1-git-send-email-architt-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
PATCH v3 7/7 dt-bindings: drm/bridge: Update bindings for ADV7533
Add description of ADV7533. Add the required and optional properties that are specific to it.
--- .../bindings/display/bridge/adi,adv7511.txt | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +20 -5
@@ -1,13 +1,19 @@ -Analog Device ADV7511(W)/13 HDMI Encoders +Analog Device ADV7511(W)/13/33 HDMI Encoders ----------------------------------------- -The ADV7511, ADV7511W and ADV7513 are HDMI audio and video transmitters +The ADV7511, ADV7511W, ADV7513 and ADV7533 are HDMI audio and video transmitters compatible with HDMI 1.4 and DVI 1.0. They support color space conversion, -S/PDIF, CEC and HDCP. +S/PDIF, CEC and HDCP. ADV7533 supports the DSI interface for input pixels, while +the others support RGB interface. Required properties: -- compatible: Should be one of "adi,adv7511", "adi,adv7511w" or "adi,adv7513" +- compatible: Should be one of: + "adi,adv7511" + "adi,adv7511w" + "adi,adv7513" + "adi,adv7533" + - reg: I2C slave address The ADV7511 supports a large number of input data formats that differ by their
@@ -32,6 +38,11 @@ The following input format properties are required except in "rgb 1x" and - adi,input-justification: The input bit justification ("left", "evenly", "right"). +The following properties are required for ADV7533: + +- adi,dsi-lanes: Number of DSI data lanes connected to the DSI host. It should + be one of 1, 2, 3 or 4. + Optional properties: - interrupts: Specifier for the ADV7511 interrupt
@@ -42,13 +53,17 @@ Optional properties: - adi,embedded-sync: The input uses synchronization signals embedded in the data stream (similar to BT.656). Defaults to separate H/V synchronization signals. +- adi,disable-timing-generator: Only for ADV7533. Disables the internal timing + generator. The chip will rely on the sync signals in the DSI data lanes, + rather than generate its own timings for HDMI output. Required nodes: The ADV7511 has two video ports. Their connections are modelled using the OF graph bindings specified in Documentation/devicetree/bindings/graph.txt. -- Video port 0 for the RGB or YUV input +- Video port 0 for the RGB, YUV or DSI input. In the case of ADV7533, the + remote endpoint phandle should refer to a valid mipi_dsi_host device node. - Video port 1 for the HDMI output
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 7/7] dt-bindings: drm/bridge: Update bindings for ADV7533
Quoted 10 lines · Archit Taneja
Add description of ADV7533. Add the required and optional properties that are specific to it.
Cc Rob Herring <[email protected]>Signed-off-by Archit Taneja <[email protected]>--- .../bindings/display/bridge/adi,adv7511.txt | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Laurent Pinchart
reviewerRe: [PATCH v3 7/7] dt-bindings: drm/bridge: Update bindings for ADV7533
In reply to Archit TanejaHi Archit,
Thank you for the patch.
Quoted 48 lines · On Wednesday 09 Mar 2016 16:27:18 Archit Taneja wrote:
Add description of ADV7533. Add the required and optional properties that are specific to it.
Cc Rob Herring <[email protected]>Signed-off-by Archit Taneja <[email protected]>--- .../bindings/display/bridge/adi,adv7511.txt | 25 ++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)diff --git
a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtb/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtindex 96c25ee..420da5a 100644Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +2
-2@@ -1,13 +1,19 @@ -Analog Device ADV7511(W)/13 HDMI Encoders +Analog Device ADV7511(W)/13/33 HDMI Encoders ----------------------------------------- -The ADV7511, ADV7511W and ADV7513 are HDMI audio and video transmitters +The ADV7511, ADV7511W, ADV7513 and ADV7533 are HDMI audio and videotransmitters compatible with HDMI 1.4 and DVI 1.0. They support color space conversion, -S/PDIF, CEC and HDCP.
+S/PDIF, CEC and HDCP. ADV7533 supports the DSI interface for input pixels, while +the others support RGB interface.Required properties:
-- compatible: Should be one of "adi,adv7511", "adi,adv7511w" or "adi,adv7513" +- compatible: Should be one of:
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +5
-0+ "adi,adv7511" + "adi,adv7511w" + "adi,adv7513" + "adi,adv7533" + - reg: I2C slave address The ADV7511 supports a large number of input data formats that differ bytheir @@ -32,6 +38,11 @@ The following input format properties are required except in "rgb 1x" and - adi,input-justification: The input bit justification ("left", "evenly", "right").
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +3
-0+The following properties are required for ADV7533: + +- adi,dsi-lanes: Number of DSI data lanes connected to the DSI host. It
Quoted 1 line
should + be one of 1, 2, 3 or 4.
Does the ADV7533 support data lanes remapping ?
Quoted 10 lines
Optional properties:
- interrupts: Specifier for the ADV7511 interrupt
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +0
-0@@ -42,13 +53,17 @@ Optional properties: - adi,embedded-sync: The input uses synchronization signals embedded in thedata stream (similar to BT.656). Defaults to separate H/V synchronization signals.
+- adi,disable-timing-generator: Only for ADV7533. Disables the internal timing + generator. The chip will rely on the sync signals in the DSI data lanes, + rather than generate its own timings for HDMI output.
Isn't that something that should be selectable at runtime ?
Quoted 8 lines
Required nodes:
The ADV7511 has two video ports. Their connections are modelled using the
OF graph bindings specified inDocumentation/devicetree/bindings/graph.txt.-- Video port 0 for the RGB or YUV input
+- Video port 0 for the RGB, YUV or DSI input. In the case of ADV7533, the + remote endpoint phandle should refer to a valid mipi_dsi_host device
Nitpicking, I would write "reference" instead of "refer to".
Quoted 1 line
node. - Video port 1 for the HDMI output
Signature · 8 lines
Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 7/7] dt-bindings: drm/bridge: Update bindings for ADV7533
Quoted 50 lines · Laurent Pinchart
Hi Archit,
Thank you for the patch.
Quoted 45 lines · On Wednesday 09 Mar 2016 16:27:18 Archit Taneja wrote:
Add description of ADV7533. Add the required and optional properties that are specific to it.
Cc Rob Herring <[email protected]>Signed-off-by Archit Taneja <[email protected]>--- .../bindings/display/bridge/adi,adv7511.txt | 25 ++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)diff --git
a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtb/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtindex 96c25ee..420da5a 100644Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +2
-2@@ -1,13 +1,19 @@ -Analog Device ADV7511(W)/13 HDMI Encoders +Analog Device ADV7511(W)/13/33 HDMI Encoders ----------------------------------------- -The ADV7511, ADV7511W and ADV7513 are HDMI audio and video transmitters +The ADV7511, ADV7511W, ADV7513 and ADV7533 are HDMI audio and videotransmitters compatible with HDMI 1.4 and DVI 1.0. They support color space conversion, -S/PDIF, CEC and HDCP.
+S/PDIF, CEC and HDCP. ADV7533 supports the DSI interface for input pixels, while +the others support RGB interface.Required properties:
-- compatible: Should be one of "adi,adv7511", "adi,adv7511w" or "adi,adv7513" +- compatible: Should be one of:
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +5
-0+ "adi,adv7511" + "adi,adv7511w" + "adi,adv7513" + "adi,adv7533" + - reg: I2C slave address The ADV7511 supports a large number of input data formats that differ bytheir @@ -32,6 +38,11 @@ The following input format properties are required except in "rgb 1x" and - adi,input-justification: The input bit justification ("left", "evenly", "right").
Quoted 6 lines
Quoted 4 lines
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +3
-0+The following properties are required for ADV7533: + +- adi,dsi-lanes: Number of DSI data lanes connected to the DSI host. Itshould + be one of 1, 2, 3 or 4.
Does the ADV7533 support data lanes remapping ?
It doesn't support remapping of lanes. There is only one register field that allows us to select the number of lanes.
Quoted 13 lines
Quoted 11 lines
Optional properties:
- interrupts: Specifier for the ADV7511 interrupt
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +0
-0@@ -42,13 +53,17 @@ Optional properties: - adi,embedded-sync: The input uses synchronization signals embedded in thedata stream (similar to BT.656). Defaults to separate H/V synchronization signals.
+- adi,disable-timing-generator: Only for ADV7533. Disables the internal timing + generator. The chip will rely on the sync signals in the DSI data lanes, + rather than generate its own timings for HDMI output.Isn't that something that should be selectable at runtime ?
The timing generator can be enabled/disabled at runtime. Although, we don't have a way to tell the driver whether we want to keep it enabled or not.
It's a hardware feature that works well on most platforms, but not on
all. In particular, it works well on DB410c, but causes issues with
the Hikey 96 board. The DSI host on Hikey has different clock sources that generate the display controller's pixel clock and DSI byte clock, whereas the Qualcomm SoC uses the same source. My guess is that the
ADV7533's timing generator doesn't like it when the pixel data and
clock are out of phase or something.
Since it is a hardware feature which needs tweaking, I thought it qualified as a DT property.
Quoted 11 lines
Quoted 9 lines
Required nodes:
The ADV7511 has two video ports. Their connections are modelled using the
OF graph bindings specified inDocumentation/devicetree/bindings/graph.txt.-- Video port 0 for the RGB or YUV input
+- Video port 0 for the RGB, YUV or DSI input. In the case of ADV7533, the + remote endpoint phandle should refer to a valid mipi_dsi_host deviceNitpicking, I would write "reference" instead of "refer to".
I'll fix this in the next revision.
Thanks,
Archit
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH v3 7/7] dt-bindings: drm/bridge: Update bindings for ADV7533
Hi Archit,
Quoted 20 lines · On Friday 22 Apr 2016 11:10:18 Archit Taneja wrote:
Quoted 19 lines · Laurent Pinchart
Quoted 18 lines · On Wednesday 09 Mar 2016 16:27:18 Archit Taneja wrote:
Add description of ADV7533. Add the required and optional properties that are specific to it.
Cc Rob Herring <[email protected]>Signed-off-by Archit Taneja <[email protected]>---
.../bindings/display/bridge/adi,adv7511.txt| 25 ++++++++++++-----1 file changed, 20 insertions(+), 5 deletions(-)diff --git
a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtb/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtindex 96c25ee..420da5a 100644Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +0
-0
[snip]
Quoted 20 lines
Quoted 7 lines
Quoted 5 lines
+- adi,disable-timing-generator: Only for ADV7533. Disables the internal timing
+ generator. The chip will rely on the sync signals in the DSI data lanes,
+ rather than generate its own timings for HDMI output.Isn't that something that should be selectable at runtime ?
The timing generator can be enabled/disabled at runtime. Although, we don't have a way to tell the driver whether we want to keep it enabled or not.
It's a hardware feature that works well on most platforms, but not on all. In particular, it works well on DB410c, but causes issues with the Hikey 96 board. The DSI host on Hikey has different clock sources that generate the display controller's pixel clock and DSI byte clock, whereas the Qualcomm SoC uses the same source. My guess is that the ADV7533's timing generator doesn't like it when the pixel data and clock are out of phase or something.
Quoted 2 lines
Since it is a hardware feature which needs tweaking, I thought it qualified as a DT property.
The fact that a hardware generator is present is certainly describes the hardware, but I'm not sure whether to enable it or not also qualifies as a hardware feature.
Are there use cases for using the timing generator conditionally on a given board ? As you implement support for disabling it, I assume it's not mandatory. What feature(s) do we lose if we keep it disabled ?
Signature · 8 lines
Regards, Laurent Pinchart -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 7/7] dt-bindings: drm/bridge: Update bindings for ADV7533
Quoted 49 lines · Laurent Pinchart
Hi Archit,
Quoted 20 lines · On Friday 22 Apr 2016 11:10:18 Archit Taneja wrote:
Quoted 19 lines · Laurent Pinchart
Quoted 18 lines · On Wednesday 09 Mar 2016 16:27:18 Archit Taneja wrote:
Add description of ADV7533. Add the required and optional properties that are specific to it.
Cc Rob Herring <[email protected]>Signed-off-by Archit Taneja <[email protected]>---
.../bindings/display/bridge/adi,adv7511.txt| 25 ++++++++++++-----1 file changed, 20 insertions(+), 5 deletions(-)diff --git
a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtb/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtindex 96c25ee..420da5a 100644Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +0
-0[snip]
Quoted 20 lines
Quoted 7 lines
Quoted 5 lines
+- adi,disable-timing-generator: Only for ADV7533. Disables the internal timing
+ generator. The chip will rely on the sync signals in the DSI data lanes,
+ rather than generate its own timings for HDMI output.Isn't that something that should be selectable at runtime ?
The timing generator can be enabled/disabled at runtime. Although, we don't have a way to tell the driver whether we want to keep it enabled or not.
It's a hardware feature that works well on most platforms, but not on all. In particular, it works well on DB410c, but causes issues with the Hikey 96 board. The DSI host on Hikey has different clock sources that generate the display controller's pixel clock and DSI byte clock, whereas the Qualcomm SoC uses the same source. My guess is that the ADV7533's timing generator doesn't like it when the pixel data and clock are out of phase or something.
Quoted 2 lines
Since it is a hardware feature which needs tweaking, I thought it qualified as a DT property.
Quoted 8 lines
The fact that a hardware generator is present is certainly describes the hardware, but I'm not sure whether to enable it or not also qualifies as a hardware feature.
Are there use cases for using the timing generator conditionally on a given board ? As you implement support for disabling it, I assume it's not mandatory. What feature(s) do we lose if we keep it disabled ?
The spec says it's recommended to use the internal timing generator. In the case of db410c, I observe an unstable output/flicker for certain modes if I don't enable it.
In the case of hikey platform, it's the other way round.
Xinliang, could you describe the problems you face when the timing generator is enabled?
Thanks,
Archit
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v3 7/7] dt-bindings: drm/bridge: Update bindings for ADV7533
Quoted 74 lines · Archit Taneja
Quoted 61 lines · Laurent Pinchart
Hi Archit,
Quoted 26 lines · On Friday 22 Apr 2016 11:10:18 Archit Taneja wrote:
Quoted 24 lines · Laurent Pinchart
Quoted 22 lines · On Wednesday 09 Mar 2016 16:27:18 Archit Taneja wrote:
Add description of ADV7533. Add the required and optional properties that
are specific to it.Cc Rob Herring <[email protected]>Signed-off-by Archit Taneja <[email protected]>---
.../bindings/display/bridge/adi,adv7511.txt| 25
++++++++++++-----1 file changed, 20 insertions(+), 5 deletions(-)diff --git
a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtb/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtindex
96c25ee..420da5a 100644Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +0
-0[snip]
Quoted 23 lines
Quoted 9 lines
Quoted 6 lines
+- adi,disable-timing-generator: Only for ADV7533. Disables the internal
timing
+ generator. The chip will rely on the sync signals in the DSI data lanes,
+ rather than generate its own timings for HDMI output.Isn't that something that should be selectable at runtime ?
The timing generator can be enabled/disabled at runtime. Although, we don't have a way to tell the driver whether we want to keep it enabled or not.
It's a hardware feature that works well on most platforms, but not on all. In particular, it works well on DB410c, but causes issues with the Hikey 96 board. The DSI host on Hikey has different clock sources that generate the display controller's pixel clock and DSI byte clock, whereas the Qualcomm SoC uses the same source. My guess is that the ADV7533's timing generator doesn't like it when the pixel data and clock are out of phase or something.
Quoted 2 lines
Since it is a hardware feature which needs tweaking, I thought it qualified as a DT property.
Quoted 9 lines
The fact that a hardware generator is present is certainly describes the hardware, but I'm not sure whether to enable it or not also qualifies as a hardware feature.
Are there use cases for using the timing generator conditionally on a given
board ? As you implement support for disabling it, I assume it's not mandatory. What feature(s) do we lose if we keep it disabled ?
Quoted 8 lines
The spec says it's recommended to use the internal timing generator. In the case of db410c, I observe an unstable output/flicker for certain modes if I don't enable it.
In the case of hikey platform, it's the other way round.
Xinliang, could you describe the problems you face when the timing generator is enabled?
Yes, opening the timing generator of ADV7533 can benefit the HDMI output signal.
But, for some circumstances, we need to disable timing generator:
To make modes work, the timing parameters (hfp, hbp, etc.) used by ADV7533 timing generator should match the ones used in DSI. If the timing parameters changed in DSI and these changing timing parameters can't pass to ADV7533, then it need to disable the timing generator of ADV7533 to make mode work.
Some modes in HiKey is in this case.
Thanks,
-xinliang
Quoted 8 lines
Thanks,
Archit--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 7/7] dt-bindings: drm/bridge: Update bindings for ADV7533
Quoted 84 lines · Xinliang Liu
Quoted 74 lines · Archit Taneja
Quoted 61 lines · Laurent Pinchart
Hi Archit,
Quoted 26 lines · On Friday 22 Apr 2016 11:10:18 Archit Taneja wrote:
Quoted 24 lines · Laurent Pinchart
Quoted 22 lines · On Wednesday 09 Mar 2016 16:27:18 Archit Taneja wrote:
Add description of ADV7533. Add the required and optional properties that
are specific to it.Cc Rob Herring <[email protected]>Signed-off-by Archit Taneja <[email protected]>---
.../bindings/display/bridge/adi,adv7511.txt| 25
++++++++++++-----1 file changed, 20 insertions(+), 5 deletions(-)diff --git
a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtb/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txtindex
96c25ee..420da5a 100644Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +0
-0[snip]
Quoted 23 lines
Quoted 9 lines
Quoted 6 lines
+- adi,disable-timing-generator: Only for ADV7533. Disables the internal
timing
+ generator. The chip will rely on the sync signals in the DSI data lanes,
+ rather than generate its own timings for HDMI output.Isn't that something that should be selectable at runtime ?
The timing generator can be enabled/disabled at runtime. Although, we don't have a way to tell the driver whether we want to keep it enabled or not.
It's a hardware feature that works well on most platforms, but not on all. In particular, it works well on DB410c, but causes issues with the Hikey 96 board. The DSI host on Hikey has different clock sources that generate the display controller's pixel clock and DSI byte clock, whereas the Qualcomm SoC uses the same source. My guess is that the ADV7533's timing generator doesn't like it when the pixel data and clock are out of phase or something.
Quoted 2 lines
Since it is a hardware feature which needs tweaking, I thought it qualified as a DT property.
Quoted 9 lines
The fact that a hardware generator is present is certainly describes the hardware, but I'm not sure whether to enable it or not also qualifies as a hardware feature.
Are there use cases for using the timing generator conditionally on a given
board ? As you implement support for disabling it, I assume it's not mandatory. What feature(s) do we lose if we keep it disabled ?Quoted 8 lines
The spec says it's recommended to use the internal timing generator. In the case of db410c, I observe an unstable output/flicker for certain modes if I don't enable it.
In the case of hikey platform, it's the other way round.
Xinliang, could you describe the problems you face when the timing generator is enabled?
Quoted 9 lines
Yes, opening the timing generator of ADV7533 can benefit the HDMI output signal.
But, for some circumstances, we need to disable timing generator:
To make modes work, the timing parameters (hfp, hbp, etc.) used by ADV7533 timing generator should match the ones used in DSI. If the timing parameters changed in DSI and these changing timing parameters can't pass to ADV7533, then it need to disable the timing generator of ADV7533 to make mode work.
Some modes in HiKey is in this case.
The ADV7533 chip's DSI receiver supports the DSI Video mode
sub-mode: "Non-burst Mode with sync pulses". Ideally, a DSI receiver supporting this mode should be able to reconstruct the timings using packets embedded in the controller.
With DB410c, it seems to struggle without it, and with Hikey, we need to explicitly disable it because, as I understand, the DSI controller there tweaks some of the timings parameters in the mode it wants to set.
It would have been ideal to not expose this knob in DT, but we need it for ADV7533 to work across multiple platforms.
Laurent, do you have any more thoughts on this? I'd posted out a v4 of this patch set. Please have a look when you get the chance.
Thanks,
Archit
Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi Laurent,
Quoted 25 lines · Archit Taneja
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
Quoted 7 lines
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Tested on ADV7533 chips on DB410c. It should work on the Hikey board too. I'd appreaciate if someone could test it on a ADV7511 platform since I don't have one.
Could you try this patch set on the rcar-du platform? It would help to verify if this doesn't break ADV7511.
Thanks,
Archit
Quoted 26 lines
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html[3]
https://lkml.org/lkml/2016/2/12/67[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.html[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.htmlArchit Taneja (7):
drm/i2c: adv7511: Convert todrm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7511: Create a MIPI DSI device
drm/i2c: adv7511: Use internal timing generator drm/i2c: adv7511: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533.../bindings/display/bridge/adi,adv7511.txt | 25 +- drivers/gpu/drm/i2c/adv7511.c | 539 +++++++++++++++++---- 2 files changed, 476 insertions(+), 88 deletions(-)
Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi Archit,
Quoted 32 lines · On Thursday 14 Apr 2016 20:26:11 Archit Taneja wrote:
Quoted 31 lines · Archit Taneja
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too.
After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
- The driver was designed as an I2C slave encoder. When ADV7533
patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Quoted 6 lines
Quoted 3 lines
Tested on ADV7533 chips on DB410c. It should work on the Hikey board too. I'd appreaciate if someone could test it on a ADV7511 platform since I don't have one.
Could you try this patch set on the rcar-du platform? It would help to verify if this doesn't break ADV7511.
Basic testing didn't show any regression. For the whole series,
Quoted 22 lines
Quoted 22 lines
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html
[3]
https://lkml.org/lkml/2016/2/12/67
[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.htm
l
[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.htmlArchit Taneja (7):
drm/i2c: adv7511: Convert todrm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7511: Create a MIPI DSI device
drm/i2c: adv7511: Use internal timing generator drm/i2c: adv7511: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533.../bindings/display/bridge/adi,adv7511.txt | 25 +- drivers/gpu/drm/i2c/adv7511.c | 539 +++++++++++---- 2 files changed, 476 insertions(+), 88 deletions(-)
Signature · 8 lines
Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Quoted 39 lines · Laurent Pinchart
Hi Archit,
Quoted 36 lines · On Thursday 14 Apr 2016 20:26:11 Archit Taneja wrote:
Quoted 34 lines · Archit Taneja
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too.
After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
- The driver was designed as an I2C slave encoder. When ADV7533
patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Tested on ADV7533 chips on DB410c. It should work on the Hikey board too. I'd appreaciate if someone could test it on a ADV7511 platform since I don't have one.
Quoted 6 lines
Quoted 2 lines
Could you try this patch set on the rcar-du platform? It would help to verify if this doesn't break ADV7511.
Basic testing didn't show any regression. For the whole series,
Tested-by Laurent Pinchart <[email protected]>
Thanks!
Archit
Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi Archit,
Thank you for the patches.
Quoted 14 lines · Archit Taneja
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
Quoted 10 lines
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
I also agree with Laurent Pinchart that bridge driver shoudn't get involved in in the connector creation.
It is better for KMS driver that has the whole view of the display pipeline.
In this case, I mean creating bridge driver to support ADV7533. I think this is something look like panel driver. Maybe we need to add some callback to the bridge to avoid creating connector in bridge driver.
We can refer to panel entity to see what callbacks to be added. One callback I can see is the get_modes callback might be need.
Quoted 6 lines
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Tested on ADV7533 chips on DB410c. It should work on the Hikey board too.
I have tested the this tracking branch :
https://git.linaro.org/landing-teams/working/qualcomm/kernel.git/shortlog/refs/heads/tracking-qcomlt-adv7511
it works for HiKey.
But it seems this patch set is a little different from the above branch. I think I need to tested this patch set.
Thanks,
-xinliang
Quoted 24 lines
I'd appreaciate if someone could test it on a ADV7511 platform since I don't have one.
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html[3]
https://lkml.org/lkml/2016/2/12/67[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.html[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.htmlArchit Taneja (7):
drm/i2c: adv7511: Convert todrm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7511: Create a MIPI DSI device
drm/i2c: adv7511: Use internal timing generator drm/i2c: adv7511: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533
Quoted 8 lines
.../bindings/display/bridge/adi,adv7511.txt | 25 +- drivers/gpu/drm/i2c/adv7511.c | 539 +++++++++++++++++---- 2 files changed, 476 insertions(+), 88 deletions(-)--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi,
Quoted 29 lines · Xinliang Liu
Hi Archit,
Thank you for the patches.Quoted 14 lines · Archit Taneja
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
Quoted 10 lines
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
Quoted 3 lines
I also agree with Laurent Pinchart that bridge driver shoudn't get involved in in the connector creation.
It is better for KMS driver that has the whole view of the display pipeline.
Yes, that's the eventual plan. We were thinking of creating an additional drm bridge api (drm_bridge_create_connector) that helps the KMS driver create a connector for the bridge.
Since there are certain connector related properties that the KMS driver may not be aware of, we were thinking of creating another drm_bridge op which fills up connector properties. Some properties (like whether we want POLLED HPD or not) are more platform specific, and would be parsed via the connector's DT node (that is, if DT is supported on that platform)
For now, this series creates the connector in the bridge's attach op, but relies on the KMS driver to call drm_connector_register. The other stuff I mentioned above can come later.
Quoted 13 lines
In this case, I mean creating bridge driver to support ADV7533. I think this is something look like panel driver. Maybe we need to add some callback to the bridge to avoid creating connector in bridge driver.
We can refer to panel entity to see what callbacks to be added. One callback I can see is theget_modescallback might be need.Quoted 5 lines
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Quoted 7 lines
Quoted 1 line
Tested on ADV7533 chips on DB410c. It should work on the Hikey board too.
I have tested the this tracking branch :
https://git.linaro.org/landing-teams/working/qualcomm/kernel.git/shortlog/refs/heads/tracking-qcomlt-adv7511
it works for HiKey.
But it seems this patch set is a little different from the above branch. I think I need to tested this patch set.
Yes, it would be great if you could test the posted patch set and provided a Tested-by. The patches "drm/i2c: adv7511: Init regulators" and above need to still be applied from this branch. I'll post these out in another patch set later.
Thanks,
Archit
Quoted 36 lines
Thanks,
-xinliangQuoted 32 lines
I'd appreaciate if someone could test it on a ADV7511 platform since I don't have one.
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html[3]
https://lkml.org/lkml/2016/2/12/67[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.html[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.htmlArchit Taneja (7):
drm/i2c: adv7511: Convert todrm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7511: Create a MIPI DSI device
drm/i2c: adv7511: Use internal timing generator drm/i2c: adv7511: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533.../bindings/display/bridge/adi,adv7511.txt | 25 +- drivers/gpu/drm/i2c/adv7511.c | 539 +++++++++++++++++---- 2 files changed, 476 insertions(+), 88 deletions(-)--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Quoted 53 lines · Archit Taneja
Hi,
Quoted 32 lines · Xinliang Liu
Hi Archit,
Thank you for the patches.Quoted 15 lines · Archit Taneja
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
Quoted 10 lines
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
Quoted 4 lines
I also agree with Laurent Pinchart that bridge driver shoudn't get involved in in the connector creation.
It is better for KMS driver that has the whole view of the display pipeline.Yes, that's the eventual plan. We were thinking of creating an additional drm bridge api (
drm_bridge_create_connector) that helps the KMS driver create a connector for the bridge.Since there are certain connector related properties that the KMS driver may not be aware of, we were thinking of creating another
drm_bridgeop which fills up connector properties. Some properties (like whether we want POLLED HPD or not) are more platform specific, and would be parsed via the connector's DT node (that is, if DT is supported on that platform)
Quoted 4 lines
For now, this series creates the connector in the bridge's attach op, but relies on the KMS driver to call
drm_connector_register. The other stuff I mentioned above can come later.
This is great, if we have the plan.
Quoted 25 lines
Quoted 17 lines
In this case, I mean creating bridge driver to support ADV7533. I think this is something look like panel driver. Maybe we need to add some callback to the bridge to avoid creating connector in bridge driver.
We can refer to panel entity to see what callbacks to be added. One callback I can see is theget_modescallback might be need.Quoted 6 lines
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Tested on ADV7533 chips on DB410c. It should work on the Hikey board too.
Quoted 6 lines
I have tested the this tracking branch :
https://git.linaro.org/landing-teams/working/qualcomm/kernel.git/shortlog/refs/heads/tracking-qcomlt-adv7511
it works for HiKey.
But it seems this patch set is a little different from the above branch. I think I need to tested this patch set.
Quoted 4 lines
Yes, it would be great if you could test the posted patch set and provided a Tested-by. The patches "drm/i2c: adv7511: Init regulators" and above need to still be applied from this branch. I'll post these out in another patch set later.
Sure, I will test them all.
Thanks,
-xinliang
Quoted 45 lines
Thanks,
ArchitQuoted 39 lines
Thanks,
-xinliangQuoted 35 lines
I'd appreaciate if someone could test it on a ADV7511 platform since I don't have one.
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html[3]
https://lkml.org/lkml/2016/2/12/67[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.html
[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.htmlArchit Taneja (7):
drm/i2c: adv7511: Convert todrm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7511: Create a MIPI DSI device
drm/i2c: adv7511: Use internal timing generator drm/i2c: adv7511: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533.../bindings/display/bridge/adi,adv7511.txt | 25 +- drivers/gpu/drm/i2c/adv7511.c | 539 +++++++++++++++++---- 2 files changed, 476 insertions(+), 88 deletions(-)--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
Quoted 3 lines
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Laurent Pinchart
reviewerHi Archit,
Quoted 43 lines · On Monday 18 Apr 2016 15:18:30 Archit Taneja wrote:
Quoted 26 lines · Xinliang Liu
Quoted 14 lines · Archit Taneja
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
Quoted 10 lines
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
Quoted 4 lines
I also agree with Laurent Pinchart that bridge driver shoudn't get involved in in the connector creation.
It is better for KMS driver that has the whole view of the display pipeline.Yes, that's the eventual plan. We were thinking of creating an additional drm bridge api (
drm_bridge_create_connector) that helps the KMS driver create a connector for the bridge.Since there are certain connector related properties that the KMS driver may not be aware of, we were thinking of creating another
drm_bridgeop which fills up connector properties. Some properties (like whether we want POLLED HPD or not) are more platform specific, and would be parsed via the connector's DT node (that is, if DT is supported on that platform)
Quoted 4 lines
For now, this series creates the connector in the bridge's attach op, but relies on the KMS driver to call
drm_connector_register. The other stuff I mentioned above can come later.
Do you think you'd have time to lead that effort ?
Quoted 49 lines
Quoted 11 lines
In this case, I mean creating bridge driver to support ADV7533. I think this is something look like panel driver. Maybe we need to add some callback to the bridge to avoid creating connector in bridge driver.
We can refer to panel entity to see what callbacks to be added. One callback I can see is theget_modescallback might be need.Quoted 4 lines
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Quoted 7 lines
Quoted 1 line
Tested on ADV7533 chips on DB410c. It should work on the Hikey board too.
I have tested the this tracking branch :
https://git.linaro.org/landing-teams/working/qualcomm/kernel.git/shortlog/
refs/heads/tracking-qcomlt-adv7511 it works for HiKey. But it seems this patch set is a little different from the above branch. I think I need to tested this patch set.Yes, it would be great if you could test the posted patch set and provided a Tested-by. The patches "drm/i2c: adv7511: Init regulators" and above need to still be applied from this branch. I'll post these out in another patch set later.
Quoted 25 lines
Quoted 25 lines
I'd appreaciate if someone could test it on a ADV7511 platform since I don't have one.
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html
[3]
https://lkml.org/lkml/2016/2/12/67
[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.ht
ml
[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.htmlArchit Taneja (7):
drm/i2c: adv7511: Convert todrm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7511: Create a MIPI DSI device
drm/i2c: adv7511: Use internal timing generator drm/i2c: adv7511: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533.../bindings/display/bridge/adi,adv7511.txt | 25 +- drivers/gpu/drm/i2c/adv7511.c | 539 ++++++++++---- 2 files changed, 476 insertions(+), 88 deletions(-)
Signature · 3 lines
Regards, Laurent Pinchart
Quoted 46 lines · Laurent Pinchart
Hi Archit,
Quoted 43 lines · On Monday 18 Apr 2016 15:18:30 Archit Taneja wrote:
Quoted 26 lines · Xinliang Liu
Quoted 14 lines · Archit Taneja
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
Quoted 10 lines
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
Quoted 4 lines
I also agree with Laurent Pinchart that bridge driver shoudn't get involved in in the connector creation.
It is better for KMS driver that has the whole view of the display pipeline.Yes, that's the eventual plan. We were thinking of creating an additional drm bridge api (
drm_bridge_create_connector) that helps the KMS driver create a connector for the bridge.Since there are certain connector related properties that the KMS driver may not be aware of, we were thinking of creating another
drm_bridgeop which fills up connector properties. Some properties (like whether we want POLLED HPD or not) are more platform specific, and would be parsed via the connector's DT node (that is, if DT is supported on that platform)
Quoted 6 lines
Quoted 4 lines
For now, this series creates the connector in the bridge's attach op, but relies on the KMS driver to call
drm_connector_register. The other stuff I mentioned above can come later.Do you think you'd have time to lead that effort ?
Yeah, I think I should.
I'll prepare a RFC and we can see how that goes.
Thanks,
Archit
Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Quoted 54 lines · Archit Taneja
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Tested on ADV7533 chips on DB410c. It should work on the Hikey board too. I'd appreaciate if someone could test it on a ADV7511 platform since I don't have one.
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html[3]
https://lkml.org/lkml/2016/2/12/67[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.html[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.htmlArchit Taneja (7):
drm/i2c: adv7511: Convert todrm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7511: Create a MIPI DSI device
drm/i2c: adv7511: Use internal timing generator drm/i2c: adv7511: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533
Quoted 8 lines
.../bindings/display/bridge/adi,adv7511.txt | 25 +- drivers/gpu/drm/i2c/adv7511.c | 539 +++++++++++++++++---- 2 files changed, 476 insertions(+), 88 deletions(-)--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
This patch set is Tested-by: Xinliang Liu <[email protected]>
Thanks
-xinliang
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Quoted 59 lines · Xinliang Liu
Quoted 58 lines · Archit Taneja
ADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Tested on ADV7533 chips on DB410c. It should work on the Hikey board too. I'd appreaciate if someone could test it on a ADV7511 platform since I don't have one.
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html[3]
https://lkml.org/lkml/2016/2/12/67[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.html[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.htmlArchit Taneja (7):
drm/i2c: adv7511: Convert todrm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7511: Create a MIPI DSI device
drm/i2c: adv7511: Use internal timing generator drm/i2c: adv7511: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533.../bindings/display/bridge/adi,adv7511.txt | 25 +- drivers/gpu/drm/i2c/adv7511.c | 539 +++++++++++++++++---- 2 files changed, 476 insertions(+), 88 deletions(-)
Quoted 6 lines
Quoted 4 lines
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux FoundationThis patch set is Tested-by: Xinliang Liu <[email protected]>
Thanks for testing!
Archit
Quoted 8 lines
Thanks
-xinliang
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
v4 cover drm/i2c: adv7511: ADV7533 support
In reply to Archit TanejaADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
Changes in v4:
- Separated out build for ADV7533. The original plan was to stub out the drm_mipi_dsi funcs, but that seemed like an overkill since it helped just this driver. It seems better to stub out the ADV7533 functionality altogether instead.
- Some minor DT binding corrections suggested by Laurent.
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html
[3]
https://lkml.org/lkml/2016/2/12/67
[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.html
[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.html
Archit Taneja (7):
drm/i2c: adv7511: Convert to drm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7533: Create a MIPI DSI device
drm/i2c: adv7533: Use internal timing generator drm/i2c: adv7533: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533
.../bindings/display/bridge/adi,adv7511.txt | 26 +- drivers/gpu/drm/i2c/Kconfig | 8 + drivers/gpu/drm/i2c/Makefile | 4 +- drivers/gpu/drm/i2c/adv7511.c | 333 ++++++++++++++------- drivers/gpu/drm/i2c/adv7511.h | 95 ++++++ drivers/gpu/drm/i2c/adv7533.c | 265 ++++++++++++++++ 6 files changed, 613 insertions(+), 118 deletions(-) create mode 100644 drivers/gpu/drm/i2c/adv7533.c
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v4 1/7 drm/i2c: adv7511: Convert to drm_bridge
We don't want to use the old i2c slave encoder interface anymore.
Remove that and make the i2c driver create a drm_bridge entity instead. Converting to bridges helps because the kms drivers don't need to exract encoder slave ops from this driver and use it within their own encoder/connector ops.
The driver now creates its own connector when a kms driver attaches itself to the bridge. Therefore, kms drivers don't need to create their own connectors anymore.
The old encoder slave ops are now used by the new bridge and connector entities.
--- drivers/gpu/drm/i2c/adv7511.c | 222 ++++++++++++++++++++++++++++-------------- 1 file changed, 148 insertions(+), 74 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +148 -74
@@ -14,9 +14,10 @@#include <linux/slab.h> #include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> -#include <drm/drm_encoder_slave.h> #include "adv7511.h"
@@ -36,7 +37,8 @@ struct adv7511 {bool edid_read;wait_queue_head_t wq; -struct drm_encoder *encoder; +struct drm_bridge bridge; +struct drm_connector connector;bool embedded_sync;enum adv7511_sync_polarity vsync_polarity;
@@ -48,11 +50,6 @@ struct adv7511 {struct gpio_desc *gpio_pd; }; -static struct adv7511 *encoder_to_adv7511 (struct drm_encoder *encoder) -{ -return to_encoder_slave (encoder)->slave_priv; -} -/* ADI recommended values for proper operation. */ static const struct reg_sequence adv7511_fixed_registers[] = { {0x98 ,0x03 },
@@ -446,8 +443,8 @@ static int adv7511_irq_process(struct adv7511 *adv7511)regmap_write (adv7511->regmap,ADV7511_REG_INT (0 ), irq0);regmap_write (adv7511->regmap,ADV7511_REG_INT (1 ), irq1); -if (irq0 &ADV7511_INT0_HPD && adv7511->encoder) -drm_helper_hpd_irq_event (adv7511->encoder->dev); +if (irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder) +drm_helper_hpd_irq_event (adv7511->connector.dev);if (irq0 &ADV7511_INT0_EDID_READY || irq1 &ADV7511_INT1_DDC_ERROR ) { adv7511->edid_read = true;
@@ -563,13 +560,12 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, }/* ----------------------------------------------------------------------------- -* Encoder operations +* ADV75xx helpers */ -static int adv7511_get_modes (struct drm_encoder *encoder, +static int adv7511_get_modes (struct adv7511 *adv7511,struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);struct edid *edid;unsigned int count;
@@ -606,21 +602,9 @@ static int adv7511_get_modes(struct drm_encoder *encoder,return count; } -static void adv7511_encoder_dpms (struct drm_encoder *encoder,int mode) -{ -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder); - -if (mode ==DRM_MODE_DPMS_ON ) -adv7511_power_on (adv7511); -else -adv7511_power_off (adv7511); -} -static enum drm_connector_status -adv7511_encoder_detect (struct drm_encoder *encoder, -struct drm_connector *connector) +adv7511_detect (struct adv7511 *adv7511,struct drm_connector *connector) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);enum drm_connector_status status;unsigned int val;bool hpd;
@@ -644,7 +628,7 @@ adv7511_encoder_detect(struct drm_encoder *encoder,if (status == connector_status_connected && hpd && adv7511->powered) {regcache_mark_dirty (adv7511->regmap);adv7511_power_on (adv7511); -adv7511_get_modes (encoder, connector); +adv7511_get_modes (adv7511, connector);if (adv7511->status == connector_status_connected) status = connector_status_disconnected; }else {
@@ -658,8 +642,8 @@ adv7511_encoder_detect(struct drm_encoder *encoder,return status; } -static int adv7511_encoder_mode_valid (struct drm_encoder *encoder, -struct drm_display_mode *mode) +static int adv7511_mode_valid (struct adv7511 *adv7511, +struct drm_display_mode *mode) {if (mode->clock >165000 )return MODE_CLOCK_HIGH ;
@@ -667,11 +651,10 @@ static int adv7511_encoder_mode_valid(struct drm_encoder *encoder,return MODE_OK ; } -static void adv7511_encoder_mode_set (struct drm_encoder *encoder, -struct drm_display_mode *mode, -struct drm_display_mode *adj_mode) +static void adv7511_mode_set (struct adv7511 *adv7511, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) { -struct adv7511 *adv7511 =encoder_to_adv7511 (encoder);unsigned int low_refresh_rate;unsigned int hsync_polarity =0 ;unsigned int vsync_polarity =0 ;
@@ -762,12 +745,120 @@ static void adv7511_encoder_mode_set(struct drm_encoder *encoder, adv7511->f_tmds = mode->clock; } -static const struct drm_encoder_slave_funcs adv7511_encoder_funcs = { - .dpms = adv7511_encoder_dpms, - .mode_valid = adv7511_encoder_mode_valid, - .mode_set = adv7511_encoder_mode_set, - .detect = adv7511_encoder_detect, - .get_modes = adv7511_get_modes, +/* Connector funcs */ +static struct adv7511 *connector_to_adv7511 (struct drm_connector *connector) +{ + return container_of(connector, struct adv7511, connector); +} + +static int adv7511_connector_get_modes (struct drm_connector *connector) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_get_modes (adv, connector); +} + +static struct drm_encoder * +adv7511_connector_best_encoder (struct drm_connector *connector) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv->bridge.encoder; +} + +static enum drm_mode_status +adv7511_connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_mode_valid (adv, mode); +} + +static struct drm_connector_helper_funcs adv7511_connector_helper_funcs = { + .get_modes = adv7511_connector_get_modes, + .best_encoder = adv7511_connector_best_encoder, + .mode_valid = adv7511_connector_mode_valid, +}; + +static enum drm_connector_status +adv7511_connector_detect (struct drm_connector *connector,bool force) +{ +struct adv7511 *adv =connector_to_adv7511 (connector); + +return adv7511_detect (adv, connector); +} + +static struct drm_connector_funcs adv7511_connector_funcs = { + .dpms = drm_atomic_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = adv7511_connector_detect, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +/* Bridge funcs */ +static struct adv7511 *bridge_to_adv7511 (struct drm_bridge *bridge) +{ + return container_of(bridge, struct adv7511, bridge); +} + +static void adv7511_bridge_enable (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_power_on (adv); +} + +static void adv7511_bridge_disable (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_power_off (adv); +} + +static void adv7511_bridge_mode_set (struct drm_bridge *bridge, +struct drm_display_mode *mode, +struct drm_display_mode *adj_mode) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); + +adv7511_mode_set (adv, mode, adj_mode); +} + +static int adv7511_bridge_attach (struct drm_bridge *bridge) +{ +struct adv7511 *adv =bridge_to_adv7511 (bridge); +int ret; + +if (!bridge->encoder) { +DRM_ERROR ("Parent encoder object not found" ); +return -ENODEV ; + } + + adv->connector.polled =DRM_CONNECTOR_POLL_HPD ; + + ret =drm_connector_init (bridge->dev, &adv->connector, + &adv7511_connector_funcs, +DRM_MODE_CONNECTOR_HDMIA ); +if (ret) { +DRM_ERROR ("Failed to initialize connector with drm\n" ); +return ret; + } +drm_connector_helper_add (&adv->connector, + &adv7511_connector_helper_funcs); +drm_mode_connector_attach_encoder (&adv->connector, bridge->encoder); + +return ret; +} + +static struct drm_bridge_funcs adv7511_bridge_funcs = { + .enable = adv7511_bridge_enable, + .disable = adv7511_bridge_disable, + .mode_set = adv7511_bridge_mode_set, + .attach = adv7511_bridge_attach, };/* -----------------------------------------------------------------------------
@@ -944,6 +1035,15 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)adv7511_set_link_config (adv7511, &link_config); + adv7511->bridge.funcs = &adv7511_bridge_funcs; + adv7511->bridge.of_node = dev->of_node; + + ret =drm_bridge_add (&adv7511->bridge); +if (ret) { +dev_err (dev,"failed to add adv7511 bridge\n" ); + goto err_i2c_unregister_device; + } +return 0 ; err_i2c_unregister_device:
@@ -956,6 +1056,8 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +drm_bridge_remove (&adv7511->bridge); +i2c_unregister_device (adv7511->i2c_edid);kfree (adv7511->edid);
@@ -963,20 +1065,6 @@ static int adv7511_remove(struct i2c_client *i2c)return 0 ; } -static int adv7511_encoder_init (struct i2c_client *i2c,struct drm_device *dev, -struct drm_encoder_slave *encoder) -{ - -struct adv7511 *adv7511 =i2c_get_clientdata (i2c); - - encoder->slave_priv = adv7511; - encoder->slave_funcs = &adv7511_encoder_funcs; - - adv7511->encoder = &encoder->base; - -return 0 ; -} -static const struct i2c_device_id adv7511_i2c_ids[] = { {"adv7511" ,0 }, {"adv7511w" ,0 },
@@ -993,31 +1081,17 @@ static const struct of_device_id adv7511_of_ids[] = { };MODULE_DEVICE_TABLE (of, adv7511_of_ids); -static struct drm_i2c_encoder_driver adv7511_driver = { - .i2c_driver = { - .driver = { - .name ="adv7511" , - .of_match_table = adv7511_of_ids, - }, - .id_table = adv7511_i2c_ids, - .probe = adv7511_probe, - .remove = adv7511_remove, +static struct i2c_driver adv7511_driver = { + .driver = { + .name ="adv7511" , + .of_match_table = adv7511_of_ids, }, - - .encoder_init = adv7511_encoder_init, + .id_table = adv7511_i2c_ids, + .probe = adv7511_probe, + .remove = adv7511_remove, }; -static int __init adv7511_init (void ) -{ -return drm_i2c_encoder_register (THIS_MODULE , &adv7511_driver); -} -module_init (adv7511_init); - -static void __exit adv7511_exit(void) -{ -drm_i2c_encoder_unregister (&adv7511_driver); -} -module_exit (adv7511_exit); +module_i2c_driver (adv7511_driver);MODULE_AUTHOR ("Lars-Peter Clausen <[email protected]>" );MODULE_DESCRIPTION ("ADV7511 HDMI transmitter driver" );
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v4 2/7 drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled
In reply to Archit TanejaWhen the adv7511 i2c client doesn't have an interrupt line, we observe a deadlock on caused by trying to lock drm device's mode_config.mutex twice in the same context.
Here is the sequence that causes it:
ioctl DRM_IOCTL_MODE_GETCONNECTOR from userspace
drm_mode_getconnector (acquires mode_config mutex)
connector->fill_modes()
drm_helper_probe_single_connector_modes
connector_funcs->get_modes
adv7511_encoder_get_modes
adv7511_get_edid_block
adv7511_irq_process
drm_helper_hpd_irq_event (acquires mode_config mutex again)In adv7511_irq_process, don't call drm_helper_hpd_irq_event when not called from the interrupt handler. It doesn't serve any purpose there anyway.
--- drivers/gpu/drm/i2c/adv7511.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +4 -4
@@ -427,7 +427,7 @@ static bool adv7511_hpd(struct adv7511 *adv7511)return false; } -static int adv7511_irq_process (struct adv7511 *adv7511) +static int adv7511_irq_process (struct adv7511 *adv7511,bool process_hpd) {unsigned int irq0, irq1;int ret;
@@ -443,7 +443,7 @@ static int adv7511_irq_process(struct adv7511 *adv7511)regmap_write (adv7511->regmap,ADV7511_REG_INT (0 ), irq0);regmap_write (adv7511->regmap,ADV7511_REG_INT (1 ), irq1); -if (irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder) +if (process_hpd && irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder)drm_helper_hpd_irq_event (adv7511->connector.dev);if (irq0 &ADV7511_INT0_EDID_READY || irq1 &ADV7511_INT1_DDC_ERROR ) {
@@ -461,7 +461,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid)struct adv7511 *adv7511 = devid;int ret; - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, true);return ret <0 ?IRQ_NONE :IRQ_HANDLED ; }
@@ -478,7 +478,7 @@ static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout) adv7511->edid_read, msecs_to_jiffies(timeout)); }else {for (; timeout >0 ; timeout -=25 ) { - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, false);if (ret <0 )break ;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v4 3/7 drm/i2c: adv7511: Initial support for ADV7533
In reply to Archit TanejaADV7533 is a DSI to HDMI encoder chip. It is a derivative of ADV7511, with additional blocks to translate input DSI data to parallel RGB data. Besides the ADV7511 I2C register map, it has additional registers that require to be configured to activate the DSI Rx block.
Create a new config that enables ADV7533 support. Use DT compatible strings to populate the ADV7533 type enum. Add minimal register configurations belonging to the DSI/CEC register map. Keep the ADV7533 code in a separate file.
Originally worked on by Lars-Peter Clausen <[email protected]>
--- drivers/gpu/drm/i2c/Kconfig | 7 +++ drivers/gpu/drm/i2c/Makefile | 4 +- drivers/gpu/drm/i2c/adv7511.c | 100 +++++++++++++++++++++--------------------- drivers/gpu/drm/i2c/adv7511.h | 67 ++++++++++++++++++++++++++++ drivers/gpu/drm/i2c/adv7533.c | 100 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 228 insertions(+), 50 deletions(-) create mode 100644 drivers/gpu/drm/i2c/adv7533.c
drivers/gpu/drm/i2c/Kconfig +7 -0
@@ -7,6 +7,13 @@ config DRM_I2C_ADV7511 help Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders. +config DRM_I2C_ADV7533 + bool "ADV7533 encoder" + depends on DRM_I2C_ADV7511 + default y + help + Support for the Analog Devices ADV7533 DSI to HDMI encoder. + config DRM_I2C_CH7006 tristate "Chrontel ch7006 TV encoder" default m if DRM_NOUVEAU
drivers/gpu/drm/i2c/Makefile +3 -1
@@ -1,6 +1,8 @@ ccflags-y := -Iinclude/drm -obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o +adv75xx-y := adv7511.o +adv75xx-$(CONFIG_DRM_I2C_ADV7533) += adv7533.o +obj-$(CONFIG_DRM_I2C_ADV7511) += adv75xx.o ch7006-y := ch7006_drv.o ch7006_mode.o obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
drivers/gpu/drm/i2c/adv7511.c +51 -49
191 lines not on this page · raw message
drivers/gpu/drm/i2c/adv7511.h +67 -0
77 lines not on this page · raw message
drivers/gpu/drm/i2c/adv7533.c new file +100 -0
100 lines not on this page · raw message
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v4 4/7 drm/i2c: adv7533: Create a MIPI DSI device
In reply to Archit TanejaIn order to pass DSI specific parameters to the DSI host, we need the driver to create a mipi_dsi_device DSI device that attaches to the host.
Use of_graph helpers to get the DSI host DT node. Create a MIPI DSI device using this host. Finally, attach this device to the DSI host.
Populate DT parameters (number of data lanes for now) that are required for DSI RX to work correctly. Hardcode few other parameters (rgb, embedded_sync) for now.
Select DRM_MIPI_DSI config option only when ADV7533 support is enabled.
--- drivers/gpu/drm/i2c/Kconfig | 1 + drivers/gpu/drm/i2c/adv7511.c | 40 ++++++++++++++++--- drivers/gpu/drm/i2c/adv7511.h | 20 ++++++++++ drivers/gpu/drm/i2c/adv7533.c | 91 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 144 insertions(+), 8 deletions(-)
drivers/gpu/drm/i2c/Kconfig +1 -0
@@ -10,6 +10,7 @@ config DRM_I2C_ADV7511 config DRM_I2C_ADV7533 bool "ADV7533 encoder" depends on DRM_I2C_ADV7511 + select DRM_MIPI_DSI default y help Support for the Analog Devices ADV7533 DSI to HDMI encoder.
drivers/gpu/drm/i2c/adv7511.c +34 -6
@@ -826,6 +826,9 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) &adv7511_connector_helper_funcs);drm_mode_connector_attach_encoder (&adv->connector, bridge->encoder); +if (adv->type ==ADV7533 ) + ret =adv7533_attach_dsi (adv); +return ret; }
@@ -952,11 +955,12 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)memset (&link_config,0 ,sizeof (link_config)); -if (adv7511->type ==ADV7511 ) { +if (adv7511->type ==ADV7511 ) ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; - } +else + ret =adv7533_parse_dt (dev->of_node, adv7511); +if (ret) +return ret;/* * The power down GPIO is optional. If present, toggle it from active to
@@ -1051,9 +1055,13 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +if (adv7511->type ==ADV7533 ) { +adv7533_detach_dsi (adv7511); +adv7533_uninit_cec (adv7511); + } +drm_bridge_remove (&adv7511->bridge); -adv7533_uninit_cec (adv7511);i2c_unregister_device (adv7511->i2c_edid);kfree (adv7511->edid);
@@ -1083,6 +1091,10 @@ static const struct of_device_id adv7511_of_ids[] = { };MODULE_DEVICE_TABLE (of, adv7511_of_ids); +static struct mipi_dsi_driver adv7533_dsi_driver = { + .driver.name ="adv7533" , +}; +static struct i2c_driver adv7511_driver = { .driver = { .name ="adv7511" ,
@@ -1093,7 +1105,23 @@ static struct i2c_driver adv7511_driver = { .remove = adv7511_remove, }; -module_i2c_driver (adv7511_driver); +static int __init adv7511_init (void ) +{ +if (IS_ENABLED (CONFIG_DRM_MIPI_DSI )) +mipi_dsi_driver_register (&adv7533_dsi_driver); + +return i2c_add_driver (&adv7511_driver); +} +module_init (adv7511_init); + +static void __exit adv7511_exit(void) +{ +i2c_del_driver (&adv7511_driver); + +if (IS_ENABLED (CONFIG_DRM_MIPI_DSI )) +mipi_dsi_driver_unregister (&adv7533_dsi_driver); +} +module_exit (adv7511_exit);MODULE_AUTHOR ("Lars-Peter Clausen <[email protected]>" );MODULE_DESCRIPTION ("ADV7511 HDMI transmitter driver" );
drivers/gpu/drm/i2c/adv7511.h +20 -0
@@ -14,6 +14,7 @@#include <linux/regmap.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_mipi_dsi.h> #define ADV7511_REG_CHIP_REVISION 0x00#define ADV7511_REG_N0 0x01
@@ -324,6 +325,11 @@ struct adv7511 {struct gpio_desc *gpio_pd; +/* ADV7533 DSI RX related params */ +struct device_node *host_node; +struct mipi_dsi_device *dsi; +u8 num_dsi_lanes; +enum adv7511_type type; };
@@ -333,6 +339,9 @@ void adv7533_dsi_power_off(struct adv7511 *adv);int adv7533_patch_registers (struct adv7511 *adv);void adv7533_uninit_cec (struct adv7511 *adv);int adv7533_init_cec (struct adv7511 *adv); +int adv7533_attach_dsi (struct adv7511 *adv); +void adv7533_detach_dsi (struct adv7511 *adv); +int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv);#else static inline void adv7533_dsi_power_on (struct adv7511 *adv) {
@@ -351,6 +360,17 @@ static inline int adv7533_init_cec(struct adv7511 *adv) {return -ENODEV ; } +static inline int adv7533_attach_dsi (struct adv7511 *adv) +{ +return -ENODEV ; +} +static inline void adv7533_detach_dsi (struct adv7511 *adv) +{ +} +static inline int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv) +{ +return -ENODEV ; +}#endif #endif /* __DRM_I2C_ADV7511_H__ */
drivers/gpu/drm/i2c/adv7533.c +89 -2
106 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v4 5/7 drm/i2c: adv7533: Use internal timing generator
In reply to Archit TanejaADV7533 provides an internal timing generator for certain modes that it can't use the DSI clock directly.
We've observed that HDMI is more stable with the internal timing generator, especially if there are instabilities in the DSI clock source. The data spec also seems to recommend the usage of the timing generator for all modes.
However, on some platforms, it's reported that enabling the timing generator causes instabilities with the HDMI output.
Create a DT parameter that lets a platform explicitly disable the timing generator. The timing generator is enabled by default.
--- drivers/gpu/drm/i2c/adv7511.c | 2 ++ drivers/gpu/drm/i2c/adv7511.h | 3 +++ drivers/gpu/drm/i2c/adv7533.c | 60 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +2 -0
@@ -712,6 +712,8 @@ static void adv7511_mode_set(struct adv7511 *adv7511,regmap_update_bits (adv7511->regmap,0x17 ,0x60 , (vsync_polarity <<6 ) | (hsync_polarity <<5 )); +drm_mode_copy (&adv7511->curr_mode, adj_mode); +/* * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is * supposed to give better results.
drivers/gpu/drm/i2c/adv7511.h +3 -0
@@ -306,6 +306,8 @@ struct adv7511 {enum drm_connector_status status;bool powered; +struct drm_display_mode curr_mode; +unsigned int f_tmds;unsigned int current_edid_segment;
@@ -329,6 +331,7 @@ struct adv7511 {struct device_node *host_node;struct mipi_dsi_device *dsi;u8 num_dsi_lanes; +bool use_timing_gen;enum adv7511_type type; };
drivers/gpu/drm/i2c/adv7533.c +58 -2
84 lines not on this page · raw message
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v4 6/7 drm/i2c: adv7533: Change number of DSI lanes dynamically
In reply to Archit TanejaLower modes on ADV7533 require lower number of DSI lanes for correct operation. If ADV7533 is being used with 4 DSI lanes, then switch the lanes to 3 when the target mode's pixel clock is less than 80 Mhz.
Based on patch by Andy Green <[email protected]>
--- drivers/gpu/drm/i2c/adv7511.c | 3 +++ drivers/gpu/drm/i2c/adv7511.h | 5 +++++ drivers/gpu/drm/i2c/adv7533.c | 22 ++++++++++++++++++++++ 3 files changed, 30 insertions(+)
drivers/gpu/drm/i2c/adv7511.c +3 -0
@@ -712,6 +712,9 @@ static void adv7511_mode_set(struct adv7511 *adv7511,regmap_update_bits (adv7511->regmap,0x17 ,0x60 , (vsync_polarity <<6 ) | (hsync_polarity <<5 )); +if (adv7511->type ==ADV7533 ) +adv7533_mode_set (adv7511, adj_mode); +drm_mode_copy (&adv7511->curr_mode, adj_mode);/*
drivers/gpu/drm/i2c/adv7511.h +5 -0
@@ -339,6 +339,7 @@ struct adv7511 {#ifdef CONFIG_DRM_I2C_ADV7533 void adv7533_dsi_power_on (struct adv7511 *adv);void adv7533_dsi_power_off (struct adv7511 *adv); +void adv7533_mode_set (struct adv7511 *adv,struct drm_display_mode *mode);int adv7533_patch_registers (struct adv7511 *adv);void adv7533_uninit_cec (struct adv7511 *adv);int adv7533_init_cec (struct adv7511 *adv);
@@ -352,6 +353,10 @@ static inline void adv7533_dsi_power_on(struct adv7511 *adv)static inline void adv7533_dsi_power_off (struct adv7511 *adv) { } +static inline void adv7533_mode_set (struct adv7511 *adv, +struct drm_display_mode *mode) +{ +}static inline int adv7533_patch_registers (struct adv7511 *adv) {return -ENODEV ;
drivers/gpu/drm/i2c/adv7533.c +22 -0
@@ -115,6 +115,28 @@ void adv7533_dsi_power_off(struct adv7511 *adv)regmap_write (adv->regmap_cec,0x27 ,0x0b ); } +void adv7533_mode_set (struct adv7511 *adv,struct drm_display_mode *mode) +{ +struct mipi_dsi_device *dsi = adv->dsi; +int lanes, ret; + +if (adv->num_dsi_lanes !=4 ) +return ; + +if (mode->clock >80000 ) + lanes =4 ; +else + lanes =3 ; + +if (lanes != dsi->lanes) { +mipi_dsi_detach (dsi); + dsi->lanes = lanes; + ret =mipi_dsi_attach (dsi); +if (ret) +dev_err (&dsi->dev,"failed to change host lanes\n" ); + } +} +int adv7533_patch_registers (struct adv7511 *adv) { return regmap_register_patch(adv->regmap,
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v4 7/7 dt-bindings: drm/bridge: Update bindings for ADV7533
In reply to Archit TanejaAdd description of ADV7533. Add the required and optional properties that are specific to it.
--- .../bindings/display/bridge/adi,adv7511.txt | 26 +++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +21 -5
@@ -1,13 +1,19 @@ -Analog Device ADV7511(W)/13 HDMI Encoders +Analog Device ADV7511(W)/13/33 HDMI Encoders ----------------------------------------- -The ADV7511, ADV7511W and ADV7513 are HDMI audio and video transmitters +The ADV7511, ADV7511W, ADV7513 and ADV7533 are HDMI audio and video transmitters compatible with HDMI 1.4 and DVI 1.0. They support color space conversion, -S/PDIF, CEC and HDCP. +S/PDIF, CEC and HDCP. ADV7533 supports the DSI interface for input pixels, while +the others support RGB interface. Required properties: -- compatible: Should be one of "adi,adv7511", "adi,adv7511w" or "adi,adv7513" +- compatible: Should be one of: + "adi,adv7511" + "adi,adv7511w" + "adi,adv7513" + "adi,adv7533" + - reg: I2C slave address The ADV7511 supports a large number of input data formats that differ by their
@@ -32,6 +38,11 @@ The following input format properties are required except in "rgb 1x" and - adi,input-justification: The input bit justification ("left", "evenly", "right"). +The following properties are required for ADV7533: + +- adi,dsi-lanes: Number of DSI data lanes connected to the DSI host. It should + be one of 1, 2, 3 or 4. + Optional properties: - interrupts: Specifier for the ADV7511 interrupt
@@ -42,13 +53,18 @@ Optional properties: - adi,embedded-sync: The input uses synchronization signals embedded in the data stream (similar to BT.656). Defaults to separate H/V synchronization signals. +- adi,disable-timing-generator: Only for ADV7533. Disables the internal timing + generator. The chip will rely on the sync signals in the DSI data lanes, + rather than generate its own timings for HDMI output. Required nodes: The ADV7511 has two video ports. Their connections are modelled using the OF graph bindings specified in Documentation/devicetree/bindings/graph.txt. -- Video port 0 for the RGB or YUV input +- Video port 0 for the RGB, YUV or DSI input. In the case of ADV7533, the + remote endpoint phandle should be a reference to a valid mipi_dsi_host device + node. - Video port 1 for the HDMI output
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
v5 cover drm/i2c: adv7511: ADV7533 support
In reply to Archit TanejaADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
Trying to get this driver merged has had some challenges:
- ADV7533 has an I2C control bus, but acts as a DSI peripheral too. After discussions, it was concluded that we'd want to provide an API to create MIPI DSI devices, rather than expose two different interfaces on DT. The first version [1] tried the former approach the second version [2] showed how the driver would look like if exposed 2 DT nodes. This lateset patchset relies on the MIPI DSI device creation API provided by [3], this has been accepted and should be merged for 4.6.
- The driver was designed as an I2C slave encoder. When ADV7533 patches were posted [1], it was modelled as a bridge, but ADV7511 and others were still left as I2C slave encoders. This wasn't accepted. After discussions, it was decided that ADV7511 too would be converted into a bridge driver, and all the users of ADV7511 should assume it is a bridge. This bridge conversion was done in [4]. There is still some debate over whether the bridge driver be involved in the connector creation, or the KMS driver that has the whole view of the display pipeline. This discussion shouldn't affect this patch set, though.
This patch set enables ADV7533 support with the above two issues now resolved. It also incorporates ADV7533 specific features and fixes that we've discovered since the first version of this patch was posted.
If this looks okay, I request that it gets pulled in 4.8. This patchset has been floating around since July last year.
Changes in v5:
- Fix break observed when built for x86.
- Based off current drm-misc.
- Removes best_encoder connector helper function since it isn't needed after this series:
https://lkml.org/lkml/2016/6/2/508
Changes in v4:
- Separated out build for ADV7533. The original plan was to stub out the drm_mipi_dsi funcs, but that seemed like an overkill since it helped just this driver. It seems better to stub out the ADV7533 functionality altogether instead.
- Some minor DT binding corrections suggested by Laurent.
[4]
https://lists.freedesktop.org/archives/dri-devel/2016-January/098287.html
[3]
https://lkml.org/lkml/2016/2/12/67
[2]
https://lists.freedesktop.org/archives/dri-devel/2015-September/089884.html
[1]:
https://lists.freedesktop.org/archives/dri-devel/2015-July/087088.html
Archit Taneja (7):
drm/i2c: adv7511: Convert to drm_bridge
drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled drm/i2c: adv7511: Initial support for ADV7533
drm/i2c: adv7533: Create a MIPI DSI device
drm/i2c: adv7533: Use internal timing generator drm/i2c: adv7533: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533
.../bindings/display/bridge/adi,adv7511.txt | 26 +- drivers/gpu/drm/i2c/Kconfig | 9 + drivers/gpu/drm/i2c/Makefile | 4 +- drivers/gpu/drm/i2c/adv7511.c | 324 ++++++++++++++------- drivers/gpu/drm/i2c/adv7511.h | 95 ++++++ drivers/gpu/drm/i2c/adv7533.c | 265 +++++++++++++++++ 6 files changed, 605 insertions(+), 118 deletions(-) create mode 100644 drivers/gpu/drm/i2c/adv7533.c
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v5 1/7 drm/i2c: adv7511: Convert to drm_bridge
We don't want to use the old i2c slave encoder interface anymore.
Remove that and make the i2c driver create a drm_bridge entity instead. Converting to bridges helps because the kms drivers don't need to exract encoder slave ops from this driver and use it within their own encoder/connector ops.
The driver now creates its own connector when a kms driver attaches itself to the bridge. Therefore, kms drivers don't need to create their own connectors anymore.
The old encoder slave ops are now used by the new bridge and connector entities.
The of_node member in drm_bridge is accessible only when CONFIG_OF is enabled. The driver anyway only works only when OF is available. Make the driver depend on OF in its Kconfig.
---
Changes in v5:
- Make the driver depend on CONFIG_OF
- Remove best_encoder connector helper
drivers/gpu/drm/i2c/Kconfig | 1 + drivers/gpu/drm/i2c/adv7511.c | 213 +++++++++++++++++++++++++++--------------- 2 files changed, 140 insertions(+), 74 deletions(-)
drivers/gpu/drm/i2c/Kconfig +1 -0
@@ -3,6 +3,7 @@ menu "I2C encoder or helper chips" config DRM_I2C_ADV7511 tristate "AV7511 encoder" + depends on OF select REGMAP_I2C help Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders.
drivers/gpu/drm/i2c/adv7511.c +139 -74
309 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v5 2/7 drm/i2c: adv7511: Fix mutex deadlock when interrupts are disabled
In reply to Archit TanejaWhen the adv7511 i2c client doesn't have an interrupt line, we observe a deadlock on caused by trying to lock drm device's mode_config.mutex twice in the same context.
Here is the sequence that causes it:
ioctl DRM_IOCTL_MODE_GETCONNECTOR from userspace
drm_mode_getconnector (acquires mode_config mutex)
connector->fill_modes()
drm_helper_probe_single_connector_modes
connector_funcs->get_modes
adv7511_encoder_get_modes
adv7511_get_edid_block
adv7511_irq_process
drm_helper_hpd_irq_event (acquires mode_config mutex again)In adv7511_irq_process, don't call drm_helper_hpd_irq_event when not called from the interrupt handler. It doesn't serve any purpose there anyway.
--- drivers/gpu/drm/i2c/adv7511.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +4 -4
@@ -427,7 +427,7 @@ static bool adv7511_hpd(struct adv7511 *adv7511)return false; } -static int adv7511_irq_process (struct adv7511 *adv7511) +static int adv7511_irq_process (struct adv7511 *adv7511,bool process_hpd) {unsigned int irq0, irq1;int ret;
@@ -443,7 +443,7 @@ static int adv7511_irq_process(struct adv7511 *adv7511)regmap_write (adv7511->regmap,ADV7511_REG_INT (0 ), irq0);regmap_write (adv7511->regmap,ADV7511_REG_INT (1 ), irq1); -if (irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder) +if (process_hpd && irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder)drm_helper_hpd_irq_event (adv7511->connector.dev);if (irq0 &ADV7511_INT0_EDID_READY || irq1 &ADV7511_INT1_DDC_ERROR ) {
@@ -461,7 +461,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid)struct adv7511 *adv7511 = devid;int ret; - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, true);return ret <0 ?IRQ_NONE :IRQ_HANDLED ; }
@@ -478,7 +478,7 @@ static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout) adv7511->edid_read, msecs_to_jiffies(timeout)); }else {for (; timeout >0 ; timeout -=25 ) { - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, false);if (ret <0 )break ;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v5 3/7 drm/i2c: adv7511: Initial support for ADV7533
In reply to Archit TanejaADV7533 is a DSI to HDMI encoder chip. It is a derivative of ADV7511, with additional blocks to translate input DSI data to parallel RGB data. Besides the ADV7511 I2C register map, it has additional registers that require to be configured to activate the DSI Rx block.
Create a new config that enables ADV7533 support. Use DT compatible strings to populate the ADV7533 type enum. Add minimal register configurations belonging to the DSI/CEC register map. Keep the ADV7533 code in a separate file.
Originally worked on by Lars-Peter Clausen <[email protected]>
--- drivers/gpu/drm/i2c/Kconfig | 7 +++ drivers/gpu/drm/i2c/Makefile | 4 +- drivers/gpu/drm/i2c/adv7511.c | 100 +++++++++++++++++++++--------------------- drivers/gpu/drm/i2c/adv7511.h | 67 ++++++++++++++++++++++++++++ drivers/gpu/drm/i2c/adv7533.c | 100 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 228 insertions(+), 50 deletions(-) create mode 100644 drivers/gpu/drm/i2c/adv7533.c
drivers/gpu/drm/i2c/Kconfig +7 -0
@@ -8,6 +8,13 @@ config DRM_I2C_ADV7511 help Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders. +config DRM_I2C_ADV7533 + bool "ADV7533 encoder" + depends on DRM_I2C_ADV7511 + default y + help + Support for the Analog Devices ADV7533 DSI to HDMI encoder. + config DRM_I2C_CH7006 tristate "Chrontel ch7006 TV encoder" default m if DRM_NOUVEAU
drivers/gpu/drm/i2c/Makefile +3 -1
@@ -1,6 +1,8 @@ ccflags-y := -Iinclude/drm -obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o +adv75xx-y := adv7511.o +adv75xx-$(CONFIG_DRM_I2C_ADV7533) += adv7533.o +obj-$(CONFIG_DRM_I2C_ADV7511) += adv75xx.o ch7006-y := ch7006_drv.o ch7006_mode.o obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
drivers/gpu/drm/i2c/adv7511.c +51 -49
191 lines not on this page · raw message
drivers/gpu/drm/i2c/adv7511.h +67 -0
77 lines not on this page · raw message
drivers/gpu/drm/i2c/adv7533.c new file +100 -0
100 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v5 4/7 drm/i2c: adv7533: Create a MIPI DSI device
In reply to Archit TanejaIn order to pass DSI specific parameters to the DSI host, we need the driver to create a mipi_dsi_device DSI device that attaches to the host.
Use of_graph helpers to get the DSI host DT node. Create a MIPI DSI device using this host. Finally, attach this device to the DSI host.
Populate DT parameters (number of data lanes for now) that are required for DSI RX to work correctly. Hardcode few other parameters (rgb, embedded_sync) for now.
Select DRM_MIPI_DSI config option only when ADV7533 support is enabled.
--- drivers/gpu/drm/i2c/Kconfig | 1 + drivers/gpu/drm/i2c/adv7511.c | 40 ++++++++++++++++--- drivers/gpu/drm/i2c/adv7511.h | 20 ++++++++++ drivers/gpu/drm/i2c/adv7533.c | 91 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 144 insertions(+), 8 deletions(-)
drivers/gpu/drm/i2c/Kconfig +1 -0
@@ -11,6 +11,7 @@ config DRM_I2C_ADV7511 config DRM_I2C_ADV7533 bool "ADV7533 encoder" depends on DRM_I2C_ADV7511 + select DRM_MIPI_DSI default y help Support for the Analog Devices ADV7533 DSI to HDMI encoder.
drivers/gpu/drm/i2c/adv7511.c +34 -6
@@ -817,6 +817,9 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) &adv7511_connector_helper_funcs);drm_mode_connector_attach_encoder (&adv->connector, bridge->encoder); +if (adv->type ==ADV7533 ) + ret =adv7533_attach_dsi (adv); +return ret; }
@@ -943,11 +946,12 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)memset (&link_config,0 ,sizeof (link_config)); -if (adv7511->type ==ADV7511 ) { +if (adv7511->type ==ADV7511 ) ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; - } +else + ret =adv7533_parse_dt (dev->of_node, adv7511); +if (ret) +return ret;/* * The power down GPIO is optional. If present, toggle it from active to
@@ -1042,9 +1046,13 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +if (adv7511->type ==ADV7533 ) { +adv7533_detach_dsi (adv7511); +adv7533_uninit_cec (adv7511); + } +drm_bridge_remove (&adv7511->bridge); -adv7533_uninit_cec (adv7511);i2c_unregister_device (adv7511->i2c_edid);kfree (adv7511->edid);
@@ -1074,6 +1082,10 @@ static const struct of_device_id adv7511_of_ids[] = { };MODULE_DEVICE_TABLE (of, adv7511_of_ids); +static struct mipi_dsi_driver adv7533_dsi_driver = { + .driver.name ="adv7533" , +}; +static struct i2c_driver adv7511_driver = { .driver = { .name ="adv7511" ,
@@ -1084,7 +1096,23 @@ static struct i2c_driver adv7511_driver = { .remove = adv7511_remove, }; -module_i2c_driver (adv7511_driver); +static int __init adv7511_init (void ) +{ +if (IS_ENABLED (CONFIG_DRM_MIPI_DSI )) +mipi_dsi_driver_register (&adv7533_dsi_driver); + +return i2c_add_driver (&adv7511_driver); +} +module_init (adv7511_init); + +static void __exit adv7511_exit(void) +{ +i2c_del_driver (&adv7511_driver); + +if (IS_ENABLED (CONFIG_DRM_MIPI_DSI )) +mipi_dsi_driver_unregister (&adv7533_dsi_driver); +} +module_exit (adv7511_exit);MODULE_AUTHOR ("Lars-Peter Clausen <[email protected]>" );MODULE_DESCRIPTION ("ADV7511 HDMI transmitter driver" );
drivers/gpu/drm/i2c/adv7511.h +20 -0
@@ -14,6 +14,7 @@#include <linux/regmap.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_mipi_dsi.h> #define ADV7511_REG_CHIP_REVISION 0x00#define ADV7511_REG_N0 0x01
@@ -324,6 +325,11 @@ struct adv7511 {struct gpio_desc *gpio_pd; +/* ADV7533 DSI RX related params */ +struct device_node *host_node; +struct mipi_dsi_device *dsi; +u8 num_dsi_lanes; +enum adv7511_type type; };
@@ -333,6 +339,9 @@ void adv7533_dsi_power_off(struct adv7511 *adv);int adv7533_patch_registers (struct adv7511 *adv);void adv7533_uninit_cec (struct adv7511 *adv);int adv7533_init_cec (struct adv7511 *adv); +int adv7533_attach_dsi (struct adv7511 *adv); +void adv7533_detach_dsi (struct adv7511 *adv); +int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv);#else static inline void adv7533_dsi_power_on (struct adv7511 *adv) {
@@ -351,6 +360,17 @@ static inline int adv7533_init_cec(struct adv7511 *adv) {return -ENODEV ; } +static inline int adv7533_attach_dsi (struct adv7511 *adv) +{ +return -ENODEV ; +} +static inline void adv7533_detach_dsi (struct adv7511 *adv) +{ +} +static inline int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv) +{ +return -ENODEV ; +}#endif #endif /* __DRM_I2C_ADV7511_H__ */
drivers/gpu/drm/i2c/adv7533.c +89 -2
106 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v5 5/7 drm/i2c: adv7533: Use internal timing generator
In reply to Archit TanejaADV7533 provides an internal timing generator for certain modes that it can't use the DSI clock directly.
We've observed that HDMI is more stable with the internal timing generator, especially if there are instabilities in the DSI clock source. The data spec also seems to recommend the usage of the timing generator for all modes.
However, on some platforms, it's reported that enabling the timing generator causes instabilities with the HDMI output.
Create a DT parameter that lets a platform explicitly disable the timing generator. The timing generator is enabled by default.
--- drivers/gpu/drm/i2c/adv7511.c | 2 ++ drivers/gpu/drm/i2c/adv7511.h | 3 +++ drivers/gpu/drm/i2c/adv7533.c | 60 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-)
drivers/gpu/drm/i2c/adv7511.c +2 -0
@@ -712,6 +712,8 @@ static void adv7511_mode_set(struct adv7511 *adv7511,regmap_update_bits (adv7511->regmap,0x17 ,0x60 , (vsync_polarity <<6 ) | (hsync_polarity <<5 )); +drm_mode_copy (&adv7511->curr_mode, adj_mode); +/* * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is * supposed to give better results.
drivers/gpu/drm/i2c/adv7511.h +3 -0
@@ -306,6 +306,8 @@ struct adv7511 {enum drm_connector_status status;bool powered; +struct drm_display_mode curr_mode; +unsigned int f_tmds;unsigned int current_edid_segment;
@@ -329,6 +331,7 @@ struct adv7511 {struct device_node *host_node;struct mipi_dsi_device *dsi;u8 num_dsi_lanes; +bool use_timing_gen;enum adv7511_type type; };
drivers/gpu/drm/i2c/adv7533.c +58 -2
84 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v5 6/7 drm/i2c: adv7533: Change number of DSI lanes dynamically
In reply to Archit TanejaLower modes on ADV7533 require lower number of DSI lanes for correct operation. If ADV7533 is being used with 4 DSI lanes, then switch the lanes to 3 when the target mode's pixel clock is less than 80 Mhz.
Based on patch by Andy Green <[email protected]>
--- drivers/gpu/drm/i2c/adv7511.c | 3 +++ drivers/gpu/drm/i2c/adv7511.h | 5 +++++ drivers/gpu/drm/i2c/adv7533.c | 22 ++++++++++++++++++++++ 3 files changed, 30 insertions(+)
drivers/gpu/drm/i2c/adv7511.c +3 -0
@@ -712,6 +712,9 @@ static void adv7511_mode_set(struct adv7511 *adv7511,regmap_update_bits (adv7511->regmap,0x17 ,0x60 , (vsync_polarity <<6 ) | (hsync_polarity <<5 )); +if (adv7511->type ==ADV7533 ) +adv7533_mode_set (adv7511, adj_mode); +drm_mode_copy (&adv7511->curr_mode, adj_mode);/*
drivers/gpu/drm/i2c/adv7511.h +5 -0
@@ -339,6 +339,7 @@ struct adv7511 {#ifdef CONFIG_DRM_I2C_ADV7533 void adv7533_dsi_power_on (struct adv7511 *adv);void adv7533_dsi_power_off (struct adv7511 *adv); +void adv7533_mode_set (struct adv7511 *adv,struct drm_display_mode *mode);int adv7533_patch_registers (struct adv7511 *adv);void adv7533_uninit_cec (struct adv7511 *adv);int adv7533_init_cec (struct adv7511 *adv);
@@ -352,6 +353,10 @@ static inline void adv7533_dsi_power_on(struct adv7511 *adv)static inline void adv7533_dsi_power_off (struct adv7511 *adv) { } +static inline void adv7533_mode_set (struct adv7511 *adv, +struct drm_display_mode *mode) +{ +}static inline int adv7533_patch_registers (struct adv7511 *adv) {return -ENODEV ;
drivers/gpu/drm/i2c/adv7533.c +22 -0
@@ -115,6 +115,28 @@ void adv7533_dsi_power_off(struct adv7511 *adv)regmap_write (adv->regmap_cec,0x27 ,0x0b ); } +void adv7533_mode_set (struct adv7511 *adv,struct drm_display_mode *mode) +{ +struct mipi_dsi_device *dsi = adv->dsi; +int lanes, ret; + +if (adv->num_dsi_lanes !=4 ) +return ; + +if (mode->clock >80000 ) + lanes =4 ; +else + lanes =3 ; + +if (lanes != dsi->lanes) { +mipi_dsi_detach (dsi); + dsi->lanes = lanes; + ret =mipi_dsi_attach (dsi); +if (ret) +dev_err (&dsi->dev,"failed to change host lanes\n" ); + } +} +int adv7533_patch_registers (struct adv7511 *adv) { return regmap_register_patch(adv->regmap,
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v5 7/7 dt-bindings: drm/bridge: Update bindings for ADV7533
In reply to Archit TanejaAdd description of ADV7533. Add the required and optional properties that are specific to it.
--- .../bindings/display/bridge/adi,adv7511.txt | 26 +++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +21 -5
@@ -1,13 +1,19 @@ -Analog Device ADV7511(W)/13 HDMI Encoders +Analog Device ADV7511(W)/13/33 HDMI Encoders ----------------------------------------- -The ADV7511, ADV7511W and ADV7513 are HDMI audio and video transmitters +The ADV7511, ADV7511W, ADV7513 and ADV7533 are HDMI audio and video transmitters compatible with HDMI 1.4 and DVI 1.0. They support color space conversion, -S/PDIF, CEC and HDCP. +S/PDIF, CEC and HDCP. ADV7533 supports the DSI interface for input pixels, while +the others support RGB interface. Required properties: -- compatible: Should be one of "adi,adv7511", "adi,adv7511w" or "adi,adv7513" +- compatible: Should be one of: + "adi,adv7511" + "adi,adv7511w" + "adi,adv7513" + "adi,adv7533" + - reg: I2C slave address The ADV7511 supports a large number of input data formats that differ by their
@@ -32,6 +38,11 @@ The following input format properties are required except in "rgb 1x" and - adi,input-justification: The input bit justification ("left", "evenly", "right"). +The following properties are required for ADV7533: + +- adi,dsi-lanes: Number of DSI data lanes connected to the DSI host. It should + be one of 1, 2, 3 or 4. + Optional properties: - interrupts: Specifier for the ADV7511 interrupt
@@ -42,13 +53,18 @@ Optional properties: - adi,embedded-sync: The input uses synchronization signals embedded in the data stream (similar to BT.656). Defaults to separate H/V synchronization signals. +- adi,disable-timing-generator: Only for ADV7533. Disables the internal timing + generator. The chip will rely on the sync signals in the DSI data lanes, + rather than generate its own timings for HDMI output. Required nodes: The ADV7511 has two video ports. Their connections are modelled using the OF graph bindings specified in Documentation/devicetree/bindings/graph.txt. -- Video port 0 for the RGB or YUV input +- Video port 0 for the RGB, YUV or DSI input. In the case of ADV7533, the + remote endpoint phandle should be a reference to a valid mipi_dsi_host device + node. - Video port 1 for the HDMI output
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
v6 cover drm/i2c: adv7511: ADV7533 support
In reply to Archit TanejaADV7533 is a DSI to HDMI encoder chip. It's like ADV7511, but with an additional DSI RX block that takes in DSI video mode output.
This revision is quite similar to the previous version with some issues fixed.
Changes in v6:
- v5 changed the adv7511 module name to adv75xx.ko, it was previously called adv7511.ko. This revision fixes the Makefile such that the module name doesn't change, and hence not break userspace.
- Move the driver to the drivers/gpu/drm/bridge folder. This was planned to be done later, but I thought it would be better if we did it in this patchset itself since the driver is already converted to a bridge.
Changes in v5:
- Fix break observed when built for x86.
- Based off current drm-misc.
- Removes best_encoder connector helper function since it isn't needed after this series:
https://lkml.org/lkml/2016/6/2/508
Changes in v4:
- Separated out build for ADV7533. The original plan was to stub out the drm_mipi_dsi funcs, but that seemed like an overkill since it helped just this driver. It seems better to stub out the ADV7533 functionality altogether instead.
- Some minor DT binding corrections suggested by Laurent.
Archit Taneja (8):
drm/i2c: adv7511: Convert to drm_bridge
drm/i2c: adv7511: Move to bridge folder
drm/bridge: adv7511: Fix mutex deadlock when interrupts are disabled drm/bridge: adv7533: Initial support for ADV7533 drm/bridge: adv7533: Create a MIPI DSI device
drm/bridge: adv7533: Use internal timing generator drm/bridge: adv7533: Change number of DSI lanes dynamically
dt-bindings: drm/bridge: Update bindings for ADV7533
.../bindings/display/bridge/adi,adv7511.txt | 26 +- drivers/gpu/drm/bridge/Kconfig | 2 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/adv7511/Kconfig | 15 + drivers/gpu/drm/bridge/adv7511/Makefile | 3 + drivers/gpu/drm/bridge/adv7511/adv7511.h | 392 +++++++ drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1124 ++++++++++++++++++++ drivers/gpu/drm/bridge/adv7511/adv7533.c | 265 +++++ drivers/gpu/drm/i2c/Kconfig | 6 - drivers/gpu/drm/i2c/Makefile | 2 - drivers/gpu/drm/i2c/adv7511.c | 1024 ------------------ drivers/gpu/drm/i2c/adv7511.h | 289 ----- 12 files changed, 1823 insertions(+), 1326 deletions(-) create mode 100644 drivers/gpu/drm/bridge/adv7511/Kconfig create mode 100644 drivers/gpu/drm/bridge/adv7511/Makefile create mode 100644 drivers/gpu/drm/bridge/adv7511/adv7511.h create mode 100644 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c create mode 100644 drivers/gpu/drm/bridge/adv7511/adv7533.c delete mode 100644 drivers/gpu/drm/i2c/adv7511.c delete mode 100644 drivers/gpu/drm/i2c/adv7511.h
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v6 1/8 drm/i2c: adv7511: Convert to drm_bridge
We don't want to use the old i2c slave encoder interface anymore.
Remove that and make the i2c driver create a drm_bridge entity instead. Converting to bridges helps because the kms drivers don't need to exract encoder slave ops from this driver and use it within their own encoder/connector ops.
The driver now creates its own connector when a kms driver attaches itself to the bridge. Therefore, kms drivers don't need to create their own connectors anymore.
The old encoder slave ops are now used by the new bridge and connector entities.
The of_node member in drm_bridge is accessible only when CONFIG_OF is enabled. The driver anyway only works only when OF is available. Make the driver depend on OF in its Kconfig.
--- drivers/gpu/drm/i2c/Kconfig | 1 + drivers/gpu/drm/i2c/adv7511.c | 213 +++++++++++++++++++++++++++--------------- 2 files changed, 140 insertions(+), 74 deletions(-)
drivers/gpu/drm/i2c/Kconfig +1 -0
@@ -3,6 +3,7 @@ menu "I2C encoder or helper chips" config DRM_I2C_ADV7511 tristate "AV7511 encoder" + depends on OF select REGMAP_I2C help Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders.
drivers/gpu/drm/i2c/adv7511.c +139 -74
309 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v6 2/8 drm/i2c: adv7511: Move to bridge folder
In reply to Archit TanejaThe driver has been converted to use drm_bridge instead of drm_i2c_slave_encoder. We can now move it to the bridge folder.
Create a separate folder since we already have a couple of files and expect more when we support audio and ADV7533.
Rename the driver to adv7511_drv.c. This will come in handy later when the driver module will need to be built from multiple object files.
---
v6:
- New patch
drivers/gpu/drm/bridge/Kconfig | 2 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/adv7511/Kconfig | 7 + drivers/gpu/drm/bridge/adv7511/Makefile | 2 + drivers/gpu/drm/bridge/adv7511/adv7511.h | 289 +++++++ drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1089 ++++++++++++++++++++++++++ drivers/gpu/drm/i2c/Kconfig | 7 - drivers/gpu/drm/i2c/Makefile | 2 - drivers/gpu/drm/i2c/adv7511.c | 1089 -------------------------- drivers/gpu/drm/i2c/adv7511.h | 289 ------- 10 files changed, 1390 insertions(+), 1387 deletions(-) create mode 100644 drivers/gpu/drm/bridge/adv7511/Kconfig create mode 100644 drivers/gpu/drm/bridge/adv7511/Makefile create mode 100644 drivers/gpu/drm/bridge/adv7511/adv7511.h create mode 100644 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c delete mode 100644 drivers/gpu/drm/i2c/adv7511.c delete mode 100644 drivers/gpu/drm/i2c/adv7511.h
drivers/gpu/drm/bridge/Kconfig +2 -0
@@ -52,4 +52,6 @@ config DRM_PARADE_PS8622 source "drivers/gpu/drm/bridge/analogix/Kconfig" +source "drivers/gpu/drm/bridge/adv7511/Kconfig" + endmenu
drivers/gpu/drm/bridge/Makefile +1 -0
@@ -6,3 +6,4 @@ obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ +obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
drivers/gpu/drm/bridge/adv7511/Kconfig new file +7 -0
@@ -0,0 +1,7 @@ +config DRM_I2C_ADV7511 + tristate "AV7511 encoder" + depends on OF + select DRM_KMS_HELPER + select REGMAP_I2C + help + Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders.
drivers/gpu/drm/bridge/adv7511/Makefile new file +2 -0
@@ -0,0 +1,2 @@ +adv7511-y := adv7511_drv.o +obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o
drivers/gpu/drm/bridge/adv7511/adv7511.h new file +289 -0
289 lines not on this page · raw message
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c new file +1089 -0
1,089 lines not on this page · raw message
drivers/gpu/drm/i2c/Kconfig +0 -7
@@ -1,13 +1,6 @@ menu "I2C encoder or helper chips" depends on DRM && DRM_KMS_HELPER && I2C -config DRM_I2C_ADV7511 - tristate "AV7511 encoder" - depends on OF - select REGMAP_I2C - help - Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders. - config DRM_I2C_CH7006 tristate "Chrontel ch7006 TV encoder" default m if DRM_NOUVEAU
drivers/gpu/drm/i2c/Makefile +0 -2
@@ -1,7 +1,5 @@ ccflags-y := -Iinclude/drm -obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o - ch7006-y := ch7006_drv.o ch7006_mode.o obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
drivers/gpu/drm/i2c/adv7511.c deleted +0 -1089
1,089 lines not on this page · raw message
drivers/gpu/drm/i2c/adv7511.h deleted +0 -289
289 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v6 3/8 drm/bridge: adv7511: Fix mutex deadlock when interrupts are disabled
In reply to Archit TanejaWhen the adv7511 i2c client doesn't have an interrupt line, we observe a deadlock on caused by trying to lock drm device's mode_config.mutex twice in the same context.
Here is the sequence that causes it:
ioctl DRM_IOCTL_MODE_GETCONNECTOR from userspace
drm_mode_getconnector (acquires mode_config mutex)
connector->fill_modes()
drm_helper_probe_single_connector_modes
connector_funcs->get_modes
adv7511_encoder_get_modes
adv7511_get_edid_block
adv7511_irq_process
drm_helper_hpd_irq_event (acquires mode_config mutex again)In adv7511_irq_process, don't call drm_helper_hpd_irq_event when not called from the interrupt handler. It doesn't serve any purpose there anyway.
--- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +4 -4
@@ -427,7 +427,7 @@ static bool adv7511_hpd(struct adv7511 *adv7511)return false; } -static int adv7511_irq_process (struct adv7511 *adv7511) +static int adv7511_irq_process (struct adv7511 *adv7511,bool process_hpd) {unsigned int irq0, irq1;int ret;
@@ -443,7 +443,7 @@ static int adv7511_irq_process(struct adv7511 *adv7511)regmap_write (adv7511->regmap,ADV7511_REG_INT (0 ), irq0);regmap_write (adv7511->regmap,ADV7511_REG_INT (1 ), irq1); -if (irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder) +if (process_hpd && irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder)drm_helper_hpd_irq_event (adv7511->connector.dev);if (irq0 &ADV7511_INT0_EDID_READY || irq1 &ADV7511_INT1_DDC_ERROR ) {
@@ -461,7 +461,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid)struct adv7511 *adv7511 = devid;int ret; - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, true);return ret <0 ?IRQ_NONE :IRQ_HANDLED ; }
@@ -478,7 +478,7 @@ static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout) adv7511->edid_read, msecs_to_jiffies(timeout)); }else {for (; timeout >0 ; timeout -=25 ) { - ret =adv7511_irq_process (adv7511); + ret =adv7511_irq_process (adv7511, false);if (ret <0 )break ;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v6 4/8 drm/bridge: adv7533: Initial support for ADV7533
In reply to Archit TanejaADV7533 is a DSI to HDMI encoder chip. It is a derivative of ADV7511, with additional blocks to translate input DSI data to parallel RGB data. Besides the ADV7511 I2C register map, it has additional registers that require to be configured to activate the DSI Rx block.
Create a new config that enables ADV7533 support. Use DT compatible strings to populate the ADV7533 type enum. Add minimal register configurations belonging to the DSI/CEC register map. Keep the ADV7533 code in a separate file.
Originally worked on by Lars-Peter Clausen <[email protected]>
--- drivers/gpu/drm/bridge/adv7511/Kconfig | 7 ++ drivers/gpu/drm/bridge/adv7511/Makefile | 1 + drivers/gpu/drm/bridge/adv7511/adv7511.h | 71 +++++++++++++++++++ drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 100 ++++++++++++++------------- drivers/gpu/drm/bridge/adv7511/adv7533.c | 100 +++++++++++++++++++++++++++ 5 files changed, 230 insertions(+), 49 deletions(-) create mode 100644 drivers/gpu/drm/bridge/adv7511/adv7533.c
drivers/gpu/drm/bridge/adv7511/Kconfig +7 -0
@@ -5,3 +5,10 @@ config DRM_I2C_ADV7511 select REGMAP_I2C help Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders. + +config DRM_I2C_ADV7533 + bool "ADV7533 encoder" + depends on DRM_I2C_ADV7511 + default y + help + Support for the Analog Devices ADV7533 DSI to HDMI encoder.
drivers/gpu/drm/bridge/adv7511/Makefile +1 -0
@@ -1,2 +1,3 @@ adv7511-y := adv7511_drv.o +adv7511-$(CONFIG_DRM_I2C_ADV7533) += adv7533.o obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o
drivers/gpu/drm/bridge/adv7511/adv7511.h +71 -0
81 lines not on this page · raw message
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +51 -49
191 lines not on this page · raw message
drivers/gpu/drm/bridge/adv7511/adv7533.c new file +100 -0
100 lines not on this page · raw message
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v6 5/8 drm/bridge: adv7533: Create a MIPI DSI device
In reply to Archit TanejaIn order to pass DSI specific parameters to the DSI host, we need the driver to create a mipi_dsi_device DSI device that attaches to the host.
Use of_graph helpers to get the DSI host DT node. Create a MIPI DSI device using this host. Finally, attach this device to the DSI host.
Populate DT parameters (number of data lanes for now) that are required for DSI RX to work correctly. Hardcode few other parameters (rgb, embedded_sync) for now.
Select DRM_MIPI_DSI config option only when ADV7533 support is enabled.
--- drivers/gpu/drm/bridge/adv7511/Kconfig | 1 + drivers/gpu/drm/bridge/adv7511/adv7511.h | 23 +++++++ drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 40 ++++++++++-- drivers/gpu/drm/bridge/adv7511/adv7533.c | 91 +++++++++++++++++++++++++++- 4 files changed, 147 insertions(+), 8 deletions(-)
drivers/gpu/drm/bridge/adv7511/Kconfig +1 -0
@@ -9,6 +9,7 @@ config DRM_I2C_ADV7511 config DRM_I2C_ADV7533 bool "ADV7533 encoder" depends on DRM_I2C_ADV7511 + select DRM_MIPI_DSI default y help Support for the Analog Devices ADV7533 DSI to HDMI encoder.
drivers/gpu/drm/bridge/adv7511/adv7511.h +23 -0
@@ -14,6 +14,7 @@#include <linux/regmap.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_mipi_dsi.h> #define ADV7511_REG_CHIP_REVISION 0x00#define ADV7511_REG_N0 0x01
@@ -324,6 +325,11 @@ struct adv7511 {struct gpio_desc *gpio_pd; +/* ADV7533 DSI RX related params */ +struct device_node *host_node; +struct mipi_dsi_device *dsi; +u8 num_dsi_lanes; +enum adv7511_type type; };
@@ -333,6 +339,9 @@ void adv7533_dsi_power_off(struct adv7511 *adv);int adv7533_patch_registers (struct adv7511 *adv);void adv7533_uninit_cec (struct adv7511 *adv);int adv7533_init_cec (struct adv7511 *adv); +int adv7533_attach_dsi (struct adv7511 *adv); +void adv7533_detach_dsi (struct adv7511 *adv); +int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv);#else static inline void adv7533_dsi_power_on (struct adv7511 *adv) {
@@ -355,6 +364,20 @@ static inline int adv7533_init_cec(struct adv7511 *adv) {return -ENODEV ; } + +static inline int adv7533_attach_dsi (struct adv7511 *adv) +{ +return -ENODEV ; +} + +static inline void adv7533_detach_dsi (struct adv7511 *adv) +{ +} + +static inline int adv7533_parse_dt (struct device_node *np,struct adv7511 *adv) +{ +return -ENODEV ; +}#endif #endif /* __DRM_I2C_ADV7511_H__ */
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +34 -6
@@ -817,6 +817,9 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) &adv7511_connector_helper_funcs);drm_mode_connector_attach_encoder (&adv->connector, bridge->encoder); +if (adv->type ==ADV7533 ) + ret =adv7533_attach_dsi (adv); +return ret; }
@@ -943,11 +946,12 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)memset (&link_config,0 ,sizeof (link_config)); -if (adv7511->type ==ADV7511 ) { +if (adv7511->type ==ADV7511 ) ret =adv7511_parse_dt (dev->of_node, &link_config); -if (ret) -return ret; - } +else + ret =adv7533_parse_dt (dev->of_node, adv7511); +if (ret) +return ret;/* * The power down GPIO is optional. If present, toggle it from active to
@@ -1042,9 +1046,13 @@ static int adv7511_remove(struct i2c_client *i2c) {struct adv7511 *adv7511 =i2c_get_clientdata (i2c); +if (adv7511->type ==ADV7533 ) { +adv7533_detach_dsi (adv7511); +adv7533_uninit_cec (adv7511); + } +drm_bridge_remove (&adv7511->bridge); -adv7533_uninit_cec (adv7511);i2c_unregister_device (adv7511->i2c_edid);kfree (adv7511->edid);
@@ -1074,6 +1082,10 @@ static const struct of_device_id adv7511_of_ids[] = { };MODULE_DEVICE_TABLE (of, adv7511_of_ids); +static struct mipi_dsi_driver adv7533_dsi_driver = { + .driver.name ="adv7533" , +}; +static struct i2c_driver adv7511_driver = { .driver = { .name ="adv7511" ,
@@ -1084,7 +1096,23 @@ static struct i2c_driver adv7511_driver = { .remove = adv7511_remove, }; -module_i2c_driver (adv7511_driver); +static int __init adv7511_init (void ) +{ +if (IS_ENABLED (CONFIG_DRM_MIPI_DSI )) +mipi_dsi_driver_register (&adv7533_dsi_driver); + +return i2c_add_driver (&adv7511_driver); +} +module_init (adv7511_init); + +static void __exit adv7511_exit(void) +{ +i2c_del_driver (&adv7511_driver); + +if (IS_ENABLED (CONFIG_DRM_MIPI_DSI )) +mipi_dsi_driver_unregister (&adv7533_dsi_driver); +} +module_exit (adv7511_exit);MODULE_AUTHOR ("Lars-Peter Clausen <[email protected]>" );MODULE_DESCRIPTION ("ADV7511 HDMI transmitter driver" );
drivers/gpu/drm/bridge/adv7511/adv7533.c +89 -2
106 lines not on this page · raw message
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v6 6/8 drm/bridge: adv7533: Use internal timing generator
In reply to Archit TanejaADV7533 provides an internal timing generator for certain modes that it can't use the DSI clock directly.
We've observed that HDMI is more stable with the internal timing generator, especially if there are instabilities in the DSI clock source. The data spec also seems to recommend the usage of the timing generator for all modes.
However, on some platforms, it's reported that enabling the timing generator causes instabilities with the HDMI output.
Create a DT parameter that lets a platform explicitly disable the timing generator. The timing generator is enabled by default.
--- drivers/gpu/drm/bridge/adv7511/adv7511.h | 3 ++ drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 2 + drivers/gpu/drm/bridge/adv7511/adv7533.c | 60 +++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 2 deletions(-)
drivers/gpu/drm/bridge/adv7511/adv7511.h +3 -0
@@ -306,6 +306,8 @@ struct adv7511 {enum drm_connector_status status;bool powered; +struct drm_display_mode curr_mode; +unsigned int f_tmds;unsigned int current_edid_segment;
@@ -329,6 +331,7 @@ struct adv7511 {struct device_node *host_node;struct mipi_dsi_device *dsi;u8 num_dsi_lanes; +bool use_timing_gen;enum adv7511_type type; };
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +2 -0
@@ -712,6 +712,8 @@ static void adv7511_mode_set(struct adv7511 *adv7511,regmap_update_bits (adv7511->regmap,0x17 ,0x60 , (vsync_polarity <<6 ) | (hsync_polarity <<5 )); +drm_mode_copy (&adv7511->curr_mode, adj_mode); +/* * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is * supposed to give better results.
drivers/gpu/drm/bridge/adv7511/adv7533.c +58 -2
84 lines not on this page · raw message
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v6 7/8 drm/bridge: adv7533: Change number of DSI lanes dynamically
In reply to Archit TanejaLower modes on ADV7533 require lower number of DSI lanes for correct operation. If ADV7533 is being used with 4 DSI lanes, then switch the lanes to 3 when the target mode's pixel clock is less than 80 Mhz.
Based on patch by Andy Green <[email protected]>
--- drivers/gpu/drm/bridge/adv7511/adv7511.h | 6 ++++++ drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 3 +++ drivers/gpu/drm/bridge/adv7511/adv7533.c | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+)
drivers/gpu/drm/bridge/adv7511/adv7511.h +6 -0
@@ -339,6 +339,7 @@ struct adv7511 {#ifdef CONFIG_DRM_I2C_ADV7533 void adv7533_dsi_power_on (struct adv7511 *adv);void adv7533_dsi_power_off (struct adv7511 *adv); +void adv7533_mode_set (struct adv7511 *adv,struct drm_display_mode *mode);int adv7533_patch_registers (struct adv7511 *adv);void adv7533_uninit_cec (struct adv7511 *adv);int adv7533_init_cec (struct adv7511 *adv);
@@ -354,6 +355,11 @@ static inline void adv7533_dsi_power_off(struct adv7511 *adv) { } +static inline void adv7533_mode_set (struct adv7511 *adv, +struct drm_display_mode *mode) +{ +} +static inline int adv7533_patch_registers (struct adv7511 *adv) {return -ENODEV ;
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +3 -0
@@ -712,6 +712,9 @@ static void adv7511_mode_set(struct adv7511 *adv7511,regmap_update_bits (adv7511->regmap,0x17 ,0x60 , (vsync_polarity <<6 ) | (hsync_polarity <<5 )); +if (adv7511->type ==ADV7533 ) +adv7533_mode_set (adv7511, adj_mode); +drm_mode_copy (&adv7511->curr_mode, adj_mode);/*
drivers/gpu/drm/bridge/adv7511/adv7533.c +22 -0
@@ -115,6 +115,28 @@ void adv7533_dsi_power_off(struct adv7511 *adv)regmap_write (adv->regmap_cec,0x27 ,0x0b ); } +void adv7533_mode_set (struct adv7511 *adv,struct drm_display_mode *mode) +{ +struct mipi_dsi_device *dsi = adv->dsi; +int lanes, ret; + +if (adv->num_dsi_lanes !=4 ) +return ; + +if (mode->clock >80000 ) + lanes =4 ; +else + lanes =3 ; + +if (lanes != dsi->lanes) { +mipi_dsi_detach (dsi); + dsi->lanes = lanes; + ret =mipi_dsi_attach (dsi); +if (ret) +dev_err (&dsi->dev,"failed to change host lanes\n" ); + } +} +int adv7533_patch_registers (struct adv7511 *adv) { return regmap_register_patch(adv->regmap,
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v6 8/8 dt-bindings: drm/bridge: Update bindings for ADV7533
In reply to Archit TanejaAdd description of ADV7533. Add the required and optional properties that are specific to it.
--- .../bindings/display/bridge/adi,adv7511.txt | 26 +++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +21 -5
@@ -1,13 +1,19 @@ -Analog Device ADV7511(W)/13 HDMI Encoders +Analog Device ADV7511(W)/13/33 HDMI Encoders ----------------------------------------- -The ADV7511, ADV7511W and ADV7513 are HDMI audio and video transmitters +The ADV7511, ADV7511W, ADV7513 and ADV7533 are HDMI audio and video transmitters compatible with HDMI 1.4 and DVI 1.0. They support color space conversion, -S/PDIF, CEC and HDCP. +S/PDIF, CEC and HDCP. ADV7533 supports the DSI interface for input pixels, while +the others support RGB interface. Required properties: -- compatible: Should be one of "adi,adv7511", "adi,adv7511w" or "adi,adv7513" +- compatible: Should be one of: + "adi,adv7511" + "adi,adv7511w" + "adi,adv7513" + "adi,adv7533" + - reg: I2C slave address The ADV7511 supports a large number of input data formats that differ by their
@@ -32,6 +38,11 @@ The following input format properties are required except in "rgb 1x" and - adi,input-justification: The input bit justification ("left", "evenly", "right"). +The following properties are required for ADV7533: + +- adi,dsi-lanes: Number of DSI data lanes connected to the DSI host. It should + be one of 1, 2, 3 or 4. + Optional properties: - interrupts: Specifier for the ADV7511 interrupt
@@ -42,13 +53,18 @@ Optional properties: - adi,embedded-sync: The input uses synchronization signals embedded in the data stream (similar to BT.656). Defaults to separate H/V synchronization signals. +- adi,disable-timing-generator: Only for ADV7533. Disables the internal timing + generator. The chip will rely on the sync signals in the DSI data lanes, + rather than generate its own timings for HDMI output. Required nodes: The ADV7511 has two video ports. Their connections are modelled using the OF graph bindings specified in Documentation/devicetree/bindings/graph.txt. -- Video port 0 for the RGB or YUV input +- Video port 0 for the RGB, YUV or DSI input. In the case of ADV7533, the + remote endpoint phandle should be a reference to a valid mipi_dsi_host device + node. - Video port 1 for the HDMI output
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation