Skip to content

Commit 2437e7c

Browse files
committed
drm/bridge: adv7533: Initial support for ADV7533
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 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]> Signed-off-by: Archit Taneja <[email protected]>
1 parent f0bfcc2 commit 2437e7c

File tree

5 files changed

+230
-49
lines changed

5 files changed

+230
-49
lines changed

drivers/gpu/drm/bridge/adv7511/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@ config DRM_I2C_ADV7511
55
select REGMAP_I2C
66
help
77
Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders.
8+
9+
config DRM_I2C_ADV7533
10+
bool "ADV7533 encoder"
11+
depends on DRM_I2C_ADV7511
12+
default y
13+
help
14+
Support for the Analog Devices ADV7533 DSI to HDMI encoder.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
adv7511-y := adv7511_drv.o
2+
adv7511-$(CONFIG_DRM_I2C_ADV7533) += adv7533.o
23
obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o

drivers/gpu/drm/bridge/adv7511/adv7511.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#define __DRM_I2C_ADV7511_H__
1111

1212
#include <linux/hdmi.h>
13+
#include <linux/i2c.h>
14+
#include <linux/regmap.h>
15+
16+
#include <drm/drm_crtc_helper.h>
1317

1418
#define ADV7511_REG_CHIP_REVISION 0x00
1519
#define ADV7511_REG_N0 0x01
@@ -286,4 +290,71 @@ struct adv7511_video_config {
286290
struct hdmi_avi_infoframe avi_infoframe;
287291
};
288292

293+
enum adv7511_type {
294+
ADV7511,
295+
ADV7533,
296+
};
297+
298+
struct adv7511 {
299+
struct i2c_client *i2c_main;
300+
struct i2c_client *i2c_edid;
301+
struct i2c_client *i2c_cec;
302+
303+
struct regmap *regmap;
304+
struct regmap *regmap_cec;
305+
enum drm_connector_status status;
306+
bool powered;
307+
308+
unsigned int f_tmds;
309+
310+
unsigned int current_edid_segment;
311+
uint8_t edid_buf[256];
312+
bool edid_read;
313+
314+
wait_queue_head_t wq;
315+
struct drm_bridge bridge;
316+
struct drm_connector connector;
317+
318+
bool embedded_sync;
319+
enum adv7511_sync_polarity vsync_polarity;
320+
enum adv7511_sync_polarity hsync_polarity;
321+
bool rgb;
322+
323+
struct edid *edid;
324+
325+
struct gpio_desc *gpio_pd;
326+
327+
enum adv7511_type type;
328+
};
329+
330+
#ifdef CONFIG_DRM_I2C_ADV7533
331+
void adv7533_dsi_power_on(struct adv7511 *adv);
332+
void adv7533_dsi_power_off(struct adv7511 *adv);
333+
int adv7533_patch_registers(struct adv7511 *adv);
334+
void adv7533_uninit_cec(struct adv7511 *adv);
335+
int adv7533_init_cec(struct adv7511 *adv);
336+
#else
337+
static inline void adv7533_dsi_power_on(struct adv7511 *adv)
338+
{
339+
}
340+
341+
static inline void adv7533_dsi_power_off(struct adv7511 *adv)
342+
{
343+
}
344+
345+
static inline int adv7533_patch_registers(struct adv7511 *adv)
346+
{
347+
return -ENODEV;
348+
}
349+
350+
static inline void adv7533_uninit_cec(struct adv7511 *adv)
351+
{
352+
}
353+
354+
static inline int adv7533_init_cec(struct adv7511 *adv)
355+
{
356+
return -ENODEV;
357+
}
358+
#endif
359+
289360
#endif /* __DRM_I2C_ADV7511_H__ */

drivers/gpu/drm/bridge/adv7511/adv7511_drv.c

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,48 +8,17 @@
88

99
#include <linux/device.h>
1010
#include <linux/gpio/consumer.h>
11-
#include <linux/i2c.h>
1211
#include <linux/module.h>
13-
#include <linux/regmap.h>
12+
#include <linux/of_device.h>
1413
#include <linux/slab.h>
1514

1615
#include <drm/drmP.h>
1716
#include <drm/drm_atomic.h>
1817
#include <drm/drm_atomic_helper.h>
19-
#include <drm/drm_crtc_helper.h>
2018
#include <drm/drm_edid.h>
2119

2220
#include "adv7511.h"
2321

24-
struct adv7511 {
25-
struct i2c_client *i2c_main;
26-
struct i2c_client *i2c_edid;
27-
28-
struct regmap *regmap;
29-
struct regmap *packet_memory_regmap;
30-
enum drm_connector_status status;
31-
bool powered;
32-
33-
unsigned int f_tmds;
34-
35-
unsigned int current_edid_segment;
36-
uint8_t edid_buf[256];
37-
bool edid_read;
38-
39-
wait_queue_head_t wq;
40-
struct drm_bridge bridge;
41-
struct drm_connector connector;
42-
43-
bool embedded_sync;
44-
enum adv7511_sync_polarity vsync_polarity;
45-
enum adv7511_sync_polarity hsync_polarity;
46-
bool rgb;
47-
48-
struct edid *edid;
49-
50-
struct gpio_desc *gpio_pd;
51-
};
52-
5322
/* ADI recommended values for proper operation. */
5423
static const struct reg_sequence adv7511_fixed_registers[] = {
5524
{ 0x98, 0x03 },
@@ -391,6 +360,9 @@ static void adv7511_power_on(struct adv7511 *adv7511)
391360
*/
392361
regcache_sync(adv7511->regmap);
393362

363+
if (adv7511->type == ADV7533)
364+
adv7533_dsi_power_on(adv7511);
365+
394366
adv7511->powered = true;
395367
}
396368

@@ -402,6 +374,9 @@ static void adv7511_power_off(struct adv7511 *adv7511)
402374
ADV7511_POWER_POWER_DOWN);
403375
regcache_mark_dirty(adv7511->regmap);
404376

377+
if (adv7511->type == ADV7533)
378+
adv7533_dsi_power_off(adv7511);
379+
405380
adv7511->powered = false;
406381
}
407382

@@ -862,8 +837,6 @@ static int adv7511_parse_dt(struct device_node *np,
862837
const char *str;
863838
int ret;
864839

865-
memset(config, 0, sizeof(*config));
866-
867840
of_property_read_u32(np, "adi,input-depth", &config->input_color_depth);
868841
if (config->input_color_depth != 8 && config->input_color_depth != 10 &&
869842
config->input_color_depth != 12)
@@ -963,9 +936,18 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
963936
adv7511->powered = false;
964937
adv7511->status = connector_status_disconnected;
965938

966-
ret = adv7511_parse_dt(dev->of_node, &link_config);
967-
if (ret)
968-
return ret;
939+
if (dev->of_node)
940+
adv7511->type = (enum adv7511_type)of_device_get_match_data(dev);
941+
else
942+
adv7511->type = id->driver_data;
943+
944+
memset(&link_config, 0, sizeof(link_config));
945+
946+
if (adv7511->type == ADV7511) {
947+
ret = adv7511_parse_dt(dev->of_node, &link_config);
948+
if (ret)
949+
return ret;
950+
}
969951

970952
/*
971953
* The power down GPIO is optional. If present, toggle it from active to
@@ -989,8 +971,12 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
989971
return ret;
990972
dev_dbg(dev, "Rev. %d\n", val);
991973

992-
ret = regmap_register_patch(adv7511->regmap, adv7511_fixed_registers,
993-
ARRAY_SIZE(adv7511_fixed_registers));
974+
if (adv7511->type == ADV7511)
975+
ret = regmap_register_patch(adv7511->regmap,
976+
adv7511_fixed_registers,
977+
ARRAY_SIZE(adv7511_fixed_registers));
978+
else
979+
ret = adv7533_patch_registers(adv7511);
994980
if (ret)
995981
return ret;
996982

@@ -1005,6 +991,12 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
1005991
if (!adv7511->i2c_edid)
1006992
return -ENOMEM;
1007993

994+
if (adv7511->type == ADV7533) {
995+
ret = adv7533_init_cec(adv7511);
996+
if (ret)
997+
goto err_i2c_unregister_edid;
998+
}
999+
10081000
if (i2c->irq) {
10091001
init_waitqueue_head(&adv7511->wq);
10101002

@@ -1013,7 +1005,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
10131005
IRQF_ONESHOT, dev_name(dev),
10141006
adv7511);
10151007
if (ret)
1016-
goto err_i2c_unregister_device;
1008+
goto err_unregister_cec;
10171009
}
10181010

10191011
/* CEC is unused for now */
@@ -1024,20 +1016,23 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
10241016

10251017
i2c_set_clientdata(i2c, adv7511);
10261018

1027-
adv7511_set_link_config(adv7511, &link_config);
1019+
if (adv7511->type == ADV7511)
1020+
adv7511_set_link_config(adv7511, &link_config);
10281021

10291022
adv7511->bridge.funcs = &adv7511_bridge_funcs;
10301023
adv7511->bridge.of_node = dev->of_node;
10311024

10321025
ret = drm_bridge_add(&adv7511->bridge);
10331026
if (ret) {
10341027
dev_err(dev, "failed to add adv7511 bridge\n");
1035-
goto err_i2c_unregister_device;
1028+
goto err_unregister_cec;
10361029
}
10371030

10381031
return 0;
10391032

1040-
err_i2c_unregister_device:
1033+
err_unregister_cec:
1034+
adv7533_uninit_cec(adv7511);
1035+
err_i2c_unregister_edid:
10411036
i2c_unregister_device(adv7511->i2c_edid);
10421037

10431038
return ret;
@@ -1049,6 +1044,7 @@ static int adv7511_remove(struct i2c_client *i2c)
10491044

10501045
drm_bridge_remove(&adv7511->bridge);
10511046

1047+
adv7533_uninit_cec(adv7511);
10521048
i2c_unregister_device(adv7511->i2c_edid);
10531049

10541050
kfree(adv7511->edid);
@@ -1057,17 +1053,23 @@ static int adv7511_remove(struct i2c_client *i2c)
10571053
}
10581054

10591055
static const struct i2c_device_id adv7511_i2c_ids[] = {
1060-
{ "adv7511", 0 },
1061-
{ "adv7511w", 0 },
1062-
{ "adv7513", 0 },
1056+
{ "adv7511", ADV7511 },
1057+
{ "adv7511w", ADV7511 },
1058+
{ "adv7513", ADV7511 },
1059+
#ifdef CONFIG_DRM_I2C_ADV7533
1060+
{ "adv7533", ADV7533 },
1061+
#endif
10631062
{ }
10641063
};
10651064
MODULE_DEVICE_TABLE(i2c, adv7511_i2c_ids);
10661065

10671066
static const struct of_device_id adv7511_of_ids[] = {
1068-
{ .compatible = "adi,adv7511", },
1069-
{ .compatible = "adi,adv7511w", },
1070-
{ .compatible = "adi,adv7513", },
1067+
{ .compatible = "adi,adv7511", .data = (void *)ADV7511 },
1068+
{ .compatible = "adi,adv7511w", .data = (void *)ADV7511 },
1069+
{ .compatible = "adi,adv7513", .data = (void *)ADV7511 },
1070+
#ifdef CONFIG_DRM_I2C_ADV7533
1071+
{ .compatible = "adi,adv7533", .data = (void *)ADV7533 },
1072+
#endif
10711073
{ }
10721074
};
10731075
MODULE_DEVICE_TABLE(of, adv7511_of_ids);

0 commit comments

Comments
 (0)