1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
6 #include <linux/of_graph.h>
10 static const struct reg_sequence adv7533_fixed_registers
[] = {
19 static const struct reg_sequence adv7533_cec_fixed_registers
[] = {
27 static void adv7511_dsi_config_timing_gen(struct adv7511
*adv
)
29 struct mipi_dsi_device
*dsi
= adv
->dsi
;
30 struct drm_display_mode
*mode
= &adv
->curr_mode
;
31 unsigned int hsw
, hfp
, hbp
, vsw
, vfp
, vbp
;
32 u8 clock_div_by_lanes
[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */
34 hsw
= mode
->hsync_end
- mode
->hsync_start
;
35 hfp
= mode
->hsync_start
- mode
->hdisplay
;
36 hbp
= mode
->htotal
- mode
->hsync_end
;
37 vsw
= mode
->vsync_end
- mode
->vsync_start
;
38 vfp
= mode
->vsync_start
- mode
->vdisplay
;
39 vbp
= mode
->vtotal
- mode
->vsync_end
;
41 /* set pixel clock divider mode */
42 regmap_write(adv
->regmap_cec
, 0x16,
43 clock_div_by_lanes
[dsi
->lanes
- 2] << 3);
45 /* horizontal porch params */
46 regmap_write(adv
->regmap_cec
, 0x28, mode
->htotal
>> 4);
47 regmap_write(adv
->regmap_cec
, 0x29, (mode
->htotal
<< 4) & 0xff);
48 regmap_write(adv
->regmap_cec
, 0x2a, hsw
>> 4);
49 regmap_write(adv
->regmap_cec
, 0x2b, (hsw
<< 4) & 0xff);
50 regmap_write(adv
->regmap_cec
, 0x2c, hfp
>> 4);
51 regmap_write(adv
->regmap_cec
, 0x2d, (hfp
<< 4) & 0xff);
52 regmap_write(adv
->regmap_cec
, 0x2e, hbp
>> 4);
53 regmap_write(adv
->regmap_cec
, 0x2f, (hbp
<< 4) & 0xff);
55 /* vertical porch params */
56 regmap_write(adv
->regmap_cec
, 0x30, mode
->vtotal
>> 4);
57 regmap_write(adv
->regmap_cec
, 0x31, (mode
->vtotal
<< 4) & 0xff);
58 regmap_write(adv
->regmap_cec
, 0x32, vsw
>> 4);
59 regmap_write(adv
->regmap_cec
, 0x33, (vsw
<< 4) & 0xff);
60 regmap_write(adv
->regmap_cec
, 0x34, vfp
>> 4);
61 regmap_write(adv
->regmap_cec
, 0x35, (vfp
<< 4) & 0xff);
62 regmap_write(adv
->regmap_cec
, 0x36, vbp
>> 4);
63 regmap_write(adv
->regmap_cec
, 0x37, (vbp
<< 4) & 0xff);
66 void adv7533_dsi_power_on(struct adv7511
*adv
)
68 struct mipi_dsi_device
*dsi
= adv
->dsi
;
70 if (adv
->use_timing_gen
)
71 adv7511_dsi_config_timing_gen(adv
);
73 /* set number of dsi lanes */
74 regmap_write(adv
->regmap_cec
, 0x1c, dsi
->lanes
<< 4);
76 if (adv
->use_timing_gen
) {
77 /* reset internal timing generator */
78 regmap_write(adv
->regmap_cec
, 0x27, 0xcb);
79 regmap_write(adv
->regmap_cec
, 0x27, 0x8b);
80 regmap_write(adv
->regmap_cec
, 0x27, 0xcb);
82 /* disable internal timing generator */
83 regmap_write(adv
->regmap_cec
, 0x27, 0x0b);
87 regmap_write(adv
->regmap_cec
, 0x03, 0x89);
88 /* disable test mode */
89 regmap_write(adv
->regmap_cec
, 0x55, 0x00);
91 regmap_register_patch(adv
->regmap_cec
, adv7533_cec_fixed_registers
,
92 ARRAY_SIZE(adv7533_cec_fixed_registers
));
95 void adv7533_dsi_power_off(struct adv7511
*adv
)
98 regmap_write(adv
->regmap_cec
, 0x03, 0x0b);
99 /* disable internal timing generator */
100 regmap_write(adv
->regmap_cec
, 0x27, 0x0b);
103 void adv7533_mode_set(struct adv7511
*adv
, const struct drm_display_mode
*mode
)
105 struct mipi_dsi_device
*dsi
= adv
->dsi
;
108 if (adv
->num_dsi_lanes
!= 4)
111 if (mode
->clock
> 80000)
116 if (lanes
!= dsi
->lanes
) {
117 mipi_dsi_detach(dsi
);
119 ret
= mipi_dsi_attach(dsi
);
121 dev_err(&dsi
->dev
, "failed to change host lanes\n");
125 int adv7533_patch_registers(struct adv7511
*adv
)
127 return regmap_register_patch(adv
->regmap
,
128 adv7533_fixed_registers
,
129 ARRAY_SIZE(adv7533_fixed_registers
));
132 int adv7533_patch_cec_registers(struct adv7511
*adv
)
134 return regmap_register_patch(adv
->regmap_cec
,
135 adv7533_cec_fixed_registers
,
136 ARRAY_SIZE(adv7533_cec_fixed_registers
));
139 int adv7533_attach_dsi(struct adv7511
*adv
)
141 struct device
*dev
= &adv
->i2c_main
->dev
;
142 struct mipi_dsi_host
*host
;
143 struct mipi_dsi_device
*dsi
;
145 const struct mipi_dsi_device_info info
= { .type
= "adv7533",
150 host
= of_find_mipi_dsi_host_by_node(adv
->host_node
);
152 dev_err(dev
, "failed to find dsi host\n");
153 return -EPROBE_DEFER
;
156 dsi
= mipi_dsi_device_register_full(host
, &info
);
158 dev_err(dev
, "failed to create dsi device\n");
165 dsi
->lanes
= adv
->num_dsi_lanes
;
166 dsi
->format
= MIPI_DSI_FMT_RGB888
;
167 dsi
->mode_flags
= MIPI_DSI_MODE_VIDEO
| MIPI_DSI_MODE_VIDEO_SYNC_PULSE
|
168 MIPI_DSI_MODE_EOT_PACKET
| MIPI_DSI_MODE_VIDEO_HSE
;
170 ret
= mipi_dsi_attach(dsi
);
172 dev_err(dev
, "failed to attach dsi to host\n");
179 mipi_dsi_device_unregister(dsi
);
184 void adv7533_detach_dsi(struct adv7511
*adv
)
186 mipi_dsi_detach(adv
->dsi
);
187 mipi_dsi_device_unregister(adv
->dsi
);
190 int adv7533_parse_dt(struct device_node
*np
, struct adv7511
*adv
)
194 of_property_read_u32(np
, "adi,dsi-lanes", &num_lanes
);
196 if (num_lanes
< 1 || num_lanes
> 4)
199 adv
->num_dsi_lanes
= num_lanes
;
201 adv
->host_node
= of_graph_get_remote_node(np
, 0, 0);
205 of_node_put(adv
->host_node
);
207 adv
->use_timing_gen
= !of_property_read_bool(np
,
208 "adi,disable-timing-generator");
210 /* TODO: Check if these need to be parsed by DT or not */
212 adv
->embedded_sync
= false;