1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. |
4 | * Copyright (c) 2019-2020. Linaro Limited. |
5 | */ |
6 | |
7 | #include <linux/firmware.h> |
8 | #include <linux/gpio/consumer.h> |
9 | #include <linux/i2c.h> |
10 | #include <linux/interrupt.h> |
11 | #include <linux/module.h> |
12 | #include <linux/mutex.h> |
13 | #include <linux/of_graph.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/regmap.h> |
16 | #include <linux/regulator/consumer.h> |
17 | #include <linux/wait.h> |
18 | #include <linux/workqueue.h> |
19 | |
20 | #include <sound/hdmi-codec.h> |
21 | |
22 | #include <drm/drm_atomic_helper.h> |
23 | #include <drm/drm_bridge.h> |
24 | #include <drm/drm_mipi_dsi.h> |
25 | #include <drm/drm_print.h> |
26 | #include <drm/drm_probe_helper.h> |
27 | |
28 | #define EDID_BLOCK_SIZE 128 |
29 | #define EDID_NUM_BLOCKS 2 |
30 | |
31 | #define FW_FILE "lt9611uxc_fw.bin" |
32 | |
33 | struct lt9611uxc { |
34 | struct device *dev; |
35 | struct drm_bridge bridge; |
36 | struct drm_connector connector; |
37 | |
38 | struct regmap *regmap; |
39 | /* Protects all accesses to registers by stopping the on-chip MCU */ |
40 | struct mutex ocm_lock; |
41 | |
42 | struct wait_queue_head wq; |
43 | struct work_struct work; |
44 | |
45 | struct device_node *dsi0_node; |
46 | struct device_node *dsi1_node; |
47 | struct mipi_dsi_device *dsi0; |
48 | struct mipi_dsi_device *dsi1; |
49 | struct platform_device *audio_pdev; |
50 | |
51 | struct gpio_desc *reset_gpio; |
52 | struct gpio_desc *enable_gpio; |
53 | |
54 | struct regulator_bulk_data supplies[2]; |
55 | |
56 | struct i2c_client *client; |
57 | |
58 | bool hpd_supported; |
59 | bool edid_read; |
60 | /* can be accessed from different threads, so protect this with ocm_lock */ |
61 | bool hdmi_connected; |
62 | uint8_t fw_version; |
63 | }; |
64 | |
65 | #define LT9611_PAGE_CONTROL 0xff |
66 | |
67 | static const struct regmap_range_cfg lt9611uxc_ranges[] = { |
68 | { |
69 | .name = "register_range" , |
70 | .range_min = 0, |
71 | .range_max = 0xd0ff, |
72 | .selector_reg = LT9611_PAGE_CONTROL, |
73 | .selector_mask = 0xff, |
74 | .selector_shift = 0, |
75 | .window_start = 0, |
76 | .window_len = 0x100, |
77 | }, |
78 | }; |
79 | |
80 | static const struct regmap_config lt9611uxc_regmap_config = { |
81 | .reg_bits = 8, |
82 | .val_bits = 8, |
83 | .max_register = 0xffff, |
84 | .ranges = lt9611uxc_ranges, |
85 | .num_ranges = ARRAY_SIZE(lt9611uxc_ranges), |
86 | }; |
87 | |
88 | struct lt9611uxc_mode { |
89 | u16 hdisplay; |
90 | u16 vdisplay; |
91 | u8 vrefresh; |
92 | }; |
93 | |
94 | /* |
95 | * This chip supports only a fixed set of modes. |
96 | * Enumerate them here to check whether the mode is supported. |
97 | */ |
98 | static struct lt9611uxc_mode lt9611uxc_modes[] = { |
99 | { 1920, 1080, 60 }, |
100 | { 1920, 1080, 30 }, |
101 | { 1920, 1080, 25 }, |
102 | { 1366, 768, 60 }, |
103 | { 1360, 768, 60 }, |
104 | { 1280, 1024, 60 }, |
105 | { 1280, 800, 60 }, |
106 | { 1280, 720, 60 }, |
107 | { 1280, 720, 50 }, |
108 | { 1280, 720, 30 }, |
109 | { 1152, 864, 60 }, |
110 | { 1024, 768, 60 }, |
111 | { 800, 600, 60 }, |
112 | { 720, 576, 50 }, |
113 | { 720, 480, 60 }, |
114 | { 640, 480, 60 }, |
115 | }; |
116 | |
117 | static struct lt9611uxc *bridge_to_lt9611uxc(struct drm_bridge *bridge) |
118 | { |
119 | return container_of(bridge, struct lt9611uxc, bridge); |
120 | } |
121 | |
122 | static struct lt9611uxc *connector_to_lt9611uxc(struct drm_connector *connector) |
123 | { |
124 | return container_of(connector, struct lt9611uxc, connector); |
125 | } |
126 | |
127 | static void lt9611uxc_lock(struct lt9611uxc *lt9611uxc) |
128 | { |
129 | mutex_lock(<9611uxc->ocm_lock); |
130 | regmap_write(map: lt9611uxc->regmap, reg: 0x80ee, val: 0x01); |
131 | } |
132 | |
133 | static void lt9611uxc_unlock(struct lt9611uxc *lt9611uxc) |
134 | { |
135 | regmap_write(map: lt9611uxc->regmap, reg: 0x80ee, val: 0x00); |
136 | msleep(msecs: 50); |
137 | mutex_unlock(lock: <9611uxc->ocm_lock); |
138 | } |
139 | |
140 | static irqreturn_t lt9611uxc_irq_thread_handler(int irq, void *dev_id) |
141 | { |
142 | struct lt9611uxc *lt9611uxc = dev_id; |
143 | unsigned int irq_status = 0; |
144 | unsigned int hpd_status = 0; |
145 | |
146 | lt9611uxc_lock(lt9611uxc); |
147 | |
148 | regmap_read(map: lt9611uxc->regmap, reg: 0xb022, val: &irq_status); |
149 | regmap_read(map: lt9611uxc->regmap, reg: 0xb023, val: &hpd_status); |
150 | if (irq_status) |
151 | regmap_write(map: lt9611uxc->regmap, reg: 0xb022, val: 0); |
152 | |
153 | if (irq_status & BIT(0)) { |
154 | lt9611uxc->edid_read = !!(hpd_status & BIT(0)); |
155 | wake_up_all(<9611uxc->wq); |
156 | } |
157 | |
158 | if (irq_status & BIT(1)) { |
159 | lt9611uxc->hdmi_connected = hpd_status & BIT(1); |
160 | schedule_work(work: <9611uxc->work); |
161 | } |
162 | |
163 | lt9611uxc_unlock(lt9611uxc); |
164 | |
165 | return IRQ_HANDLED; |
166 | } |
167 | |
168 | static void lt9611uxc_hpd_work(struct work_struct *work) |
169 | { |
170 | struct lt9611uxc *lt9611uxc = container_of(work, struct lt9611uxc, work); |
171 | bool connected; |
172 | |
173 | if (lt9611uxc->connector.dev) { |
174 | if (lt9611uxc->connector.dev->mode_config.funcs) |
175 | drm_kms_helper_hotplug_event(dev: lt9611uxc->connector.dev); |
176 | } else { |
177 | |
178 | mutex_lock(<9611uxc->ocm_lock); |
179 | connected = lt9611uxc->hdmi_connected; |
180 | mutex_unlock(lock: <9611uxc->ocm_lock); |
181 | |
182 | drm_bridge_hpd_notify(bridge: <9611uxc->bridge, |
183 | status: connected ? |
184 | connector_status_connected : |
185 | connector_status_disconnected); |
186 | } |
187 | } |
188 | |
189 | static void lt9611uxc_reset(struct lt9611uxc *lt9611uxc) |
190 | { |
191 | gpiod_set_value_cansleep(desc: lt9611uxc->reset_gpio, value: 1); |
192 | msleep(msecs: 20); |
193 | |
194 | gpiod_set_value_cansleep(desc: lt9611uxc->reset_gpio, value: 0); |
195 | msleep(msecs: 20); |
196 | |
197 | gpiod_set_value_cansleep(desc: lt9611uxc->reset_gpio, value: 1); |
198 | msleep(msecs: 300); |
199 | } |
200 | |
201 | static void lt9611uxc_assert_5v(struct lt9611uxc *lt9611uxc) |
202 | { |
203 | if (!lt9611uxc->enable_gpio) |
204 | return; |
205 | |
206 | gpiod_set_value_cansleep(desc: lt9611uxc->enable_gpio, value: 1); |
207 | msleep(msecs: 20); |
208 | } |
209 | |
210 | static int lt9611uxc_regulator_init(struct lt9611uxc *lt9611uxc) |
211 | { |
212 | int ret; |
213 | |
214 | lt9611uxc->supplies[0].supply = "vdd" ; |
215 | lt9611uxc->supplies[1].supply = "vcc" ; |
216 | |
217 | ret = devm_regulator_bulk_get(dev: lt9611uxc->dev, num_consumers: 2, consumers: lt9611uxc->supplies); |
218 | if (ret < 0) |
219 | return ret; |
220 | |
221 | return regulator_set_load(regulator: lt9611uxc->supplies[0].consumer, load_uA: 200000); |
222 | } |
223 | |
224 | static int lt9611uxc_regulator_enable(struct lt9611uxc *lt9611uxc) |
225 | { |
226 | int ret; |
227 | |
228 | ret = regulator_enable(regulator: lt9611uxc->supplies[0].consumer); |
229 | if (ret < 0) |
230 | return ret; |
231 | |
232 | usleep_range(min: 1000, max: 10000); /* 50000 according to dtsi */ |
233 | |
234 | ret = regulator_enable(regulator: lt9611uxc->supplies[1].consumer); |
235 | if (ret < 0) { |
236 | regulator_disable(regulator: lt9611uxc->supplies[0].consumer); |
237 | return ret; |
238 | } |
239 | |
240 | return 0; |
241 | } |
242 | |
243 | static struct lt9611uxc_mode *lt9611uxc_find_mode(const struct drm_display_mode *mode) |
244 | { |
245 | int i; |
246 | |
247 | for (i = 0; i < ARRAY_SIZE(lt9611uxc_modes); i++) { |
248 | if (lt9611uxc_modes[i].hdisplay == mode->hdisplay && |
249 | lt9611uxc_modes[i].vdisplay == mode->vdisplay && |
250 | lt9611uxc_modes[i].vrefresh == drm_mode_vrefresh(mode)) { |
251 | return <9611uxc_modes[i]; |
252 | } |
253 | } |
254 | |
255 | return NULL; |
256 | } |
257 | |
258 | static struct mipi_dsi_device *lt9611uxc_attach_dsi(struct lt9611uxc *lt9611uxc, |
259 | struct device_node *dsi_node) |
260 | { |
261 | const struct mipi_dsi_device_info info = { "lt9611uxc" , 0, NULL }; |
262 | struct mipi_dsi_device *dsi; |
263 | struct mipi_dsi_host *host; |
264 | struct device *dev = lt9611uxc->dev; |
265 | int ret; |
266 | |
267 | host = of_find_mipi_dsi_host_by_node(node: dsi_node); |
268 | if (!host) { |
269 | dev_err(dev, "failed to find dsi host\n" ); |
270 | return ERR_PTR(error: -EPROBE_DEFER); |
271 | } |
272 | |
273 | dsi = devm_mipi_dsi_device_register_full(dev, host, info: &info); |
274 | if (IS_ERR(ptr: dsi)) { |
275 | dev_err(dev, "failed to create dsi device\n" ); |
276 | return dsi; |
277 | } |
278 | |
279 | dsi->lanes = 4; |
280 | dsi->format = MIPI_DSI_FMT_RGB888; |
281 | dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | |
282 | MIPI_DSI_MODE_VIDEO_HSE; |
283 | |
284 | ret = devm_mipi_dsi_attach(dev, dsi); |
285 | if (ret < 0) { |
286 | dev_err(dev, "failed to attach dsi to host\n" ); |
287 | return ERR_PTR(error: ret); |
288 | } |
289 | |
290 | return dsi; |
291 | } |
292 | |
293 | static int lt9611uxc_connector_get_modes(struct drm_connector *connector) |
294 | { |
295 | struct lt9611uxc *lt9611uxc = connector_to_lt9611uxc(connector); |
296 | unsigned int count; |
297 | struct edid *edid; |
298 | |
299 | edid = drm_bridge_get_edid(bridge: <9611uxc->bridge, connector); |
300 | drm_connector_update_edid_property(connector, edid); |
301 | count = drm_add_edid_modes(connector, edid); |
302 | kfree(objp: edid); |
303 | |
304 | return count; |
305 | } |
306 | |
307 | static enum drm_connector_status lt9611uxc_connector_detect(struct drm_connector *connector, |
308 | bool force) |
309 | { |
310 | struct lt9611uxc *lt9611uxc = connector_to_lt9611uxc(connector); |
311 | |
312 | return lt9611uxc->bridge.funcs->detect(<9611uxc->bridge); |
313 | } |
314 | |
315 | static enum drm_mode_status lt9611uxc_connector_mode_valid(struct drm_connector *connector, |
316 | struct drm_display_mode *mode) |
317 | { |
318 | struct lt9611uxc_mode *lt9611uxc_mode = lt9611uxc_find_mode(mode); |
319 | |
320 | return lt9611uxc_mode ? MODE_OK : MODE_BAD; |
321 | } |
322 | |
323 | static const struct drm_connector_helper_funcs lt9611uxc_bridge_connector_helper_funcs = { |
324 | .get_modes = lt9611uxc_connector_get_modes, |
325 | .mode_valid = lt9611uxc_connector_mode_valid, |
326 | }; |
327 | |
328 | static const struct drm_connector_funcs lt9611uxc_bridge_connector_funcs = { |
329 | .fill_modes = drm_helper_probe_single_connector_modes, |
330 | .detect = lt9611uxc_connector_detect, |
331 | .destroy = drm_connector_cleanup, |
332 | .reset = drm_atomic_helper_connector_reset, |
333 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
334 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
335 | }; |
336 | |
337 | static int lt9611uxc_connector_init(struct drm_bridge *bridge, struct lt9611uxc *lt9611uxc) |
338 | { |
339 | int ret; |
340 | |
341 | if (!bridge->encoder) { |
342 | DRM_ERROR("Parent encoder object not found" ); |
343 | return -ENODEV; |
344 | } |
345 | |
346 | lt9611uxc->connector.polled = DRM_CONNECTOR_POLL_HPD; |
347 | |
348 | drm_connector_helper_add(connector: <9611uxc->connector, |
349 | funcs: <9611uxc_bridge_connector_helper_funcs); |
350 | ret = drm_connector_init(dev: bridge->dev, connector: <9611uxc->connector, |
351 | funcs: <9611uxc_bridge_connector_funcs, |
352 | DRM_MODE_CONNECTOR_HDMIA); |
353 | if (ret) { |
354 | DRM_ERROR("Failed to initialize connector with drm\n" ); |
355 | return ret; |
356 | } |
357 | |
358 | return drm_connector_attach_encoder(connector: <9611uxc->connector, encoder: bridge->encoder); |
359 | } |
360 | |
361 | static int lt9611uxc_bridge_attach(struct drm_bridge *bridge, |
362 | enum drm_bridge_attach_flags flags) |
363 | { |
364 | struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge); |
365 | int ret; |
366 | |
367 | if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { |
368 | ret = lt9611uxc_connector_init(bridge, lt9611uxc); |
369 | if (ret < 0) |
370 | return ret; |
371 | } |
372 | |
373 | return 0; |
374 | } |
375 | |
376 | static enum drm_mode_status |
377 | lt9611uxc_bridge_mode_valid(struct drm_bridge *bridge, |
378 | const struct drm_display_info *info, |
379 | const struct drm_display_mode *mode) |
380 | { |
381 | struct lt9611uxc_mode *lt9611uxc_mode; |
382 | |
383 | lt9611uxc_mode = lt9611uxc_find_mode(mode); |
384 | |
385 | return lt9611uxc_mode ? MODE_OK : MODE_BAD; |
386 | } |
387 | |
388 | static void lt9611uxc_video_setup(struct lt9611uxc *lt9611uxc, |
389 | const struct drm_display_mode *mode) |
390 | { |
391 | u32 h_total, hactive, hsync_len, hfront_porch; |
392 | u32 v_total, vactive, vsync_len, vfront_porch; |
393 | |
394 | h_total = mode->htotal; |
395 | v_total = mode->vtotal; |
396 | |
397 | hactive = mode->hdisplay; |
398 | hsync_len = mode->hsync_end - mode->hsync_start; |
399 | hfront_porch = mode->hsync_start - mode->hdisplay; |
400 | |
401 | vactive = mode->vdisplay; |
402 | vsync_len = mode->vsync_end - mode->vsync_start; |
403 | vfront_porch = mode->vsync_start - mode->vdisplay; |
404 | |
405 | regmap_write(map: lt9611uxc->regmap, reg: 0xd00d, val: (u8)(v_total / 256)); |
406 | regmap_write(map: lt9611uxc->regmap, reg: 0xd00e, val: (u8)(v_total % 256)); |
407 | |
408 | regmap_write(map: lt9611uxc->regmap, reg: 0xd00f, val: (u8)(vactive / 256)); |
409 | regmap_write(map: lt9611uxc->regmap, reg: 0xd010, val: (u8)(vactive % 256)); |
410 | |
411 | regmap_write(map: lt9611uxc->regmap, reg: 0xd011, val: (u8)(h_total / 256)); |
412 | regmap_write(map: lt9611uxc->regmap, reg: 0xd012, val: (u8)(h_total % 256)); |
413 | |
414 | regmap_write(map: lt9611uxc->regmap, reg: 0xd013, val: (u8)(hactive / 256)); |
415 | regmap_write(map: lt9611uxc->regmap, reg: 0xd014, val: (u8)(hactive % 256)); |
416 | |
417 | regmap_write(map: lt9611uxc->regmap, reg: 0xd015, val: (u8)(vsync_len % 256)); |
418 | |
419 | regmap_update_bits(map: lt9611uxc->regmap, reg: 0xd016, mask: 0xf, val: (u8)(hsync_len / 256)); |
420 | regmap_write(map: lt9611uxc->regmap, reg: 0xd017, val: (u8)(hsync_len % 256)); |
421 | |
422 | regmap_update_bits(map: lt9611uxc->regmap, reg: 0xd018, mask: 0xf, val: (u8)(vfront_porch / 256)); |
423 | regmap_write(map: lt9611uxc->regmap, reg: 0xd019, val: (u8)(vfront_porch % 256)); |
424 | |
425 | regmap_update_bits(map: lt9611uxc->regmap, reg: 0xd01a, mask: 0xf, val: (u8)(hfront_porch / 256)); |
426 | regmap_write(map: lt9611uxc->regmap, reg: 0xd01b, val: (u8)(hfront_porch % 256)); |
427 | } |
428 | |
429 | static void lt9611uxc_bridge_mode_set(struct drm_bridge *bridge, |
430 | const struct drm_display_mode *mode, |
431 | const struct drm_display_mode *adj_mode) |
432 | { |
433 | struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge); |
434 | |
435 | lt9611uxc_lock(lt9611uxc); |
436 | lt9611uxc_video_setup(lt9611uxc, mode); |
437 | lt9611uxc_unlock(lt9611uxc); |
438 | } |
439 | |
440 | static enum drm_connector_status lt9611uxc_bridge_detect(struct drm_bridge *bridge) |
441 | { |
442 | struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge); |
443 | unsigned int reg_val = 0; |
444 | int ret; |
445 | bool connected = true; |
446 | |
447 | lt9611uxc_lock(lt9611uxc); |
448 | |
449 | if (lt9611uxc->hpd_supported) { |
450 | ret = regmap_read(map: lt9611uxc->regmap, reg: 0xb023, val: ®_val); |
451 | |
452 | if (ret) |
453 | dev_err(lt9611uxc->dev, "failed to read hpd status: %d\n" , ret); |
454 | else |
455 | connected = reg_val & BIT(1); |
456 | } |
457 | lt9611uxc->hdmi_connected = connected; |
458 | |
459 | lt9611uxc_unlock(lt9611uxc); |
460 | |
461 | return connected ? connector_status_connected : |
462 | connector_status_disconnected; |
463 | } |
464 | |
465 | static int lt9611uxc_wait_for_edid(struct lt9611uxc *lt9611uxc) |
466 | { |
467 | return wait_event_interruptible_timeout(lt9611uxc->wq, lt9611uxc->edid_read, |
468 | msecs_to_jiffies(500)); |
469 | } |
470 | |
471 | static int lt9611uxc_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) |
472 | { |
473 | struct lt9611uxc *lt9611uxc = data; |
474 | int ret; |
475 | |
476 | if (len > EDID_BLOCK_SIZE) |
477 | return -EINVAL; |
478 | |
479 | if (block >= EDID_NUM_BLOCKS) |
480 | return -EINVAL; |
481 | |
482 | lt9611uxc_lock(lt9611uxc); |
483 | |
484 | regmap_write(map: lt9611uxc->regmap, reg: 0xb00b, val: 0x10); |
485 | |
486 | regmap_write(map: lt9611uxc->regmap, reg: 0xb00a, val: block * EDID_BLOCK_SIZE); |
487 | |
488 | ret = regmap_noinc_read(map: lt9611uxc->regmap, reg: 0xb0b0, val: buf, val_len: len); |
489 | if (ret) |
490 | dev_err(lt9611uxc->dev, "edid read failed: %d\n" , ret); |
491 | |
492 | lt9611uxc_unlock(lt9611uxc); |
493 | |
494 | return 0; |
495 | }; |
496 | |
497 | static struct edid *lt9611uxc_bridge_get_edid(struct drm_bridge *bridge, |
498 | struct drm_connector *connector) |
499 | { |
500 | struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge); |
501 | int ret; |
502 | |
503 | ret = lt9611uxc_wait_for_edid(lt9611uxc); |
504 | if (ret < 0) { |
505 | dev_err(lt9611uxc->dev, "wait for EDID failed: %d\n" , ret); |
506 | return NULL; |
507 | } else if (ret == 0) { |
508 | dev_err(lt9611uxc->dev, "wait for EDID timeout\n" ); |
509 | return NULL; |
510 | } |
511 | |
512 | return drm_do_get_edid(connector, get_edid_block: lt9611uxc_get_edid_block, data: lt9611uxc); |
513 | } |
514 | |
515 | static const struct drm_bridge_funcs lt9611uxc_bridge_funcs = { |
516 | .attach = lt9611uxc_bridge_attach, |
517 | .mode_valid = lt9611uxc_bridge_mode_valid, |
518 | .mode_set = lt9611uxc_bridge_mode_set, |
519 | .detect = lt9611uxc_bridge_detect, |
520 | .get_edid = lt9611uxc_bridge_get_edid, |
521 | }; |
522 | |
523 | static int lt9611uxc_parse_dt(struct device *dev, |
524 | struct lt9611uxc *lt9611uxc) |
525 | { |
526 | lt9611uxc->dsi0_node = of_graph_get_remote_node(node: dev->of_node, port: 0, endpoint: -1); |
527 | if (!lt9611uxc->dsi0_node) { |
528 | dev_err(lt9611uxc->dev, "failed to get remote node for primary dsi\n" ); |
529 | return -ENODEV; |
530 | } |
531 | |
532 | lt9611uxc->dsi1_node = of_graph_get_remote_node(node: dev->of_node, port: 1, endpoint: -1); |
533 | |
534 | return 0; |
535 | } |
536 | |
537 | static int lt9611uxc_gpio_init(struct lt9611uxc *lt9611uxc) |
538 | { |
539 | struct device *dev = lt9611uxc->dev; |
540 | |
541 | lt9611uxc->reset_gpio = devm_gpiod_get(dev, con_id: "reset" , flags: GPIOD_OUT_HIGH); |
542 | if (IS_ERR(ptr: lt9611uxc->reset_gpio)) { |
543 | dev_err(dev, "failed to acquire reset gpio\n" ); |
544 | return PTR_ERR(ptr: lt9611uxc->reset_gpio); |
545 | } |
546 | |
547 | lt9611uxc->enable_gpio = devm_gpiod_get_optional(dev, con_id: "enable" , flags: GPIOD_OUT_LOW); |
548 | if (IS_ERR(ptr: lt9611uxc->enable_gpio)) { |
549 | dev_err(dev, "failed to acquire enable gpio\n" ); |
550 | return PTR_ERR(ptr: lt9611uxc->enable_gpio); |
551 | } |
552 | |
553 | return 0; |
554 | } |
555 | |
556 | static int lt9611uxc_read_device_rev(struct lt9611uxc *lt9611uxc) |
557 | { |
558 | unsigned int rev0, rev1, rev2; |
559 | int ret; |
560 | |
561 | lt9611uxc_lock(lt9611uxc); |
562 | |
563 | ret = regmap_read(map: lt9611uxc->regmap, reg: 0x8100, val: &rev0); |
564 | ret |= regmap_read(map: lt9611uxc->regmap, reg: 0x8101, val: &rev1); |
565 | ret |= regmap_read(map: lt9611uxc->regmap, reg: 0x8102, val: &rev2); |
566 | if (ret) |
567 | dev_err(lt9611uxc->dev, "failed to read revision: %d\n" , ret); |
568 | else |
569 | dev_info(lt9611uxc->dev, "LT9611 revision: 0x%02x.%02x.%02x\n" , rev0, rev1, rev2); |
570 | |
571 | lt9611uxc_unlock(lt9611uxc); |
572 | |
573 | return ret; |
574 | } |
575 | |
576 | static int lt9611uxc_read_version(struct lt9611uxc *lt9611uxc) |
577 | { |
578 | unsigned int rev; |
579 | int ret; |
580 | |
581 | lt9611uxc_lock(lt9611uxc); |
582 | |
583 | ret = regmap_read(map: lt9611uxc->regmap, reg: 0xb021, val: &rev); |
584 | if (ret) |
585 | dev_err(lt9611uxc->dev, "failed to read revision: %d\n" , ret); |
586 | else |
587 | dev_info(lt9611uxc->dev, "LT9611 version: 0x%02x\n" , rev); |
588 | |
589 | lt9611uxc_unlock(lt9611uxc); |
590 | |
591 | return ret < 0 ? ret : rev; |
592 | } |
593 | |
594 | static int lt9611uxc_hdmi_hw_params(struct device *dev, void *data, |
595 | struct hdmi_codec_daifmt *fmt, |
596 | struct hdmi_codec_params *hparms) |
597 | { |
598 | /* |
599 | * LT9611UXC will automatically detect rate and sample size, so no need |
600 | * to setup anything here. |
601 | */ |
602 | return 0; |
603 | } |
604 | |
605 | static void lt9611uxc_audio_shutdown(struct device *dev, void *data) |
606 | { |
607 | } |
608 | |
609 | static int lt9611uxc_hdmi_i2s_get_dai_id(struct snd_soc_component *component, |
610 | struct device_node *endpoint) |
611 | { |
612 | struct of_endpoint of_ep; |
613 | int ret; |
614 | |
615 | ret = of_graph_parse_endpoint(node: endpoint, endpoint: &of_ep); |
616 | if (ret < 0) |
617 | return ret; |
618 | |
619 | /* |
620 | * HDMI sound should be located as reg = <2> |
621 | * Then, it is sound port 0 |
622 | */ |
623 | if (of_ep.port == 2) |
624 | return 0; |
625 | |
626 | return -EINVAL; |
627 | } |
628 | |
629 | static const struct hdmi_codec_ops lt9611uxc_codec_ops = { |
630 | .hw_params = lt9611uxc_hdmi_hw_params, |
631 | .audio_shutdown = lt9611uxc_audio_shutdown, |
632 | .get_dai_id = lt9611uxc_hdmi_i2s_get_dai_id, |
633 | }; |
634 | |
635 | static int lt9611uxc_audio_init(struct device *dev, struct lt9611uxc *lt9611uxc) |
636 | { |
637 | struct hdmi_codec_pdata codec_data = { |
638 | .ops = <9611uxc_codec_ops, |
639 | .max_i2s_channels = 2, |
640 | .i2s = 1, |
641 | .data = lt9611uxc, |
642 | }; |
643 | |
644 | lt9611uxc->audio_pdev = |
645 | platform_device_register_data(parent: dev, HDMI_CODEC_DRV_NAME, |
646 | PLATFORM_DEVID_AUTO, |
647 | data: &codec_data, size: sizeof(codec_data)); |
648 | |
649 | return PTR_ERR_OR_ZERO(ptr: lt9611uxc->audio_pdev); |
650 | } |
651 | |
652 | static void lt9611uxc_audio_exit(struct lt9611uxc *lt9611uxc) |
653 | { |
654 | if (lt9611uxc->audio_pdev) { |
655 | platform_device_unregister(lt9611uxc->audio_pdev); |
656 | lt9611uxc->audio_pdev = NULL; |
657 | } |
658 | } |
659 | |
660 | #define LT9611UXC_FW_PAGE_SIZE 32 |
661 | static void lt9611uxc_firmware_write_page(struct lt9611uxc *lt9611uxc, u16 addr, const u8 *buf) |
662 | { |
663 | struct reg_sequence seq_write_prepare[] = { |
664 | REG_SEQ0(0x805a, 0x04), |
665 | REG_SEQ0(0x805a, 0x00), |
666 | |
667 | REG_SEQ0(0x805e, 0xdf), |
668 | REG_SEQ0(0x805a, 0x20), |
669 | REG_SEQ0(0x805a, 0x00), |
670 | REG_SEQ0(0x8058, 0x21), |
671 | }; |
672 | |
673 | struct reg_sequence seq_write_addr[] = { |
674 | REG_SEQ0(0x805b, (addr >> 16) & 0xff), |
675 | REG_SEQ0(0x805c, (addr >> 8) & 0xff), |
676 | REG_SEQ0(0x805d, addr & 0xff), |
677 | REG_SEQ0(0x805a, 0x10), |
678 | REG_SEQ0(0x805a, 0x00), |
679 | }; |
680 | |
681 | regmap_write(map: lt9611uxc->regmap, reg: 0x8108, val: 0xbf); |
682 | msleep(msecs: 20); |
683 | regmap_write(map: lt9611uxc->regmap, reg: 0x8108, val: 0xff); |
684 | msleep(msecs: 20); |
685 | regmap_multi_reg_write(map: lt9611uxc->regmap, regs: seq_write_prepare, ARRAY_SIZE(seq_write_prepare)); |
686 | regmap_noinc_write(map: lt9611uxc->regmap, reg: 0x8059, val: buf, LT9611UXC_FW_PAGE_SIZE); |
687 | regmap_multi_reg_write(map: lt9611uxc->regmap, regs: seq_write_addr, ARRAY_SIZE(seq_write_addr)); |
688 | msleep(msecs: 20); |
689 | } |
690 | |
691 | static void lt9611uxc_firmware_read_page(struct lt9611uxc *lt9611uxc, u16 addr, char *buf) |
692 | { |
693 | struct reg_sequence seq_read_page[] = { |
694 | REG_SEQ0(0x805a, 0xa0), |
695 | REG_SEQ0(0x805a, 0x80), |
696 | REG_SEQ0(0x805b, (addr >> 16) & 0xff), |
697 | REG_SEQ0(0x805c, (addr >> 8) & 0xff), |
698 | REG_SEQ0(0x805d, addr & 0xff), |
699 | REG_SEQ0(0x805a, 0x90), |
700 | REG_SEQ0(0x805a, 0x80), |
701 | REG_SEQ0(0x8058, 0x21), |
702 | }; |
703 | |
704 | regmap_multi_reg_write(map: lt9611uxc->regmap, regs: seq_read_page, ARRAY_SIZE(seq_read_page)); |
705 | regmap_noinc_read(map: lt9611uxc->regmap, reg: 0x805f, val: buf, LT9611UXC_FW_PAGE_SIZE); |
706 | } |
707 | |
708 | static char *lt9611uxc_firmware_read(struct lt9611uxc *lt9611uxc, size_t size) |
709 | { |
710 | struct reg_sequence seq_read_setup[] = { |
711 | REG_SEQ0(0x805a, 0x84), |
712 | REG_SEQ0(0x805a, 0x80), |
713 | }; |
714 | |
715 | char *readbuf; |
716 | u16 offset; |
717 | |
718 | readbuf = kzalloc(ALIGN(size, 32), GFP_KERNEL); |
719 | if (!readbuf) |
720 | return NULL; |
721 | |
722 | regmap_multi_reg_write(map: lt9611uxc->regmap, regs: seq_read_setup, ARRAY_SIZE(seq_read_setup)); |
723 | |
724 | for (offset = 0; |
725 | offset < size; |
726 | offset += LT9611UXC_FW_PAGE_SIZE) |
727 | lt9611uxc_firmware_read_page(lt9611uxc, addr: offset, buf: &readbuf[offset]); |
728 | |
729 | return readbuf; |
730 | } |
731 | |
732 | static int lt9611uxc_firmware_update(struct lt9611uxc *lt9611uxc) |
733 | { |
734 | int ret; |
735 | u16 offset; |
736 | size_t remain; |
737 | char *readbuf; |
738 | const struct firmware *fw; |
739 | |
740 | struct reg_sequence seq_setup[] = { |
741 | REG_SEQ0(0x805e, 0xdf), |
742 | REG_SEQ0(0x8058, 0x00), |
743 | REG_SEQ0(0x8059, 0x50), |
744 | REG_SEQ0(0x805a, 0x10), |
745 | REG_SEQ0(0x805a, 0x00), |
746 | }; |
747 | |
748 | |
749 | struct reg_sequence seq_block_erase[] = { |
750 | REG_SEQ0(0x805a, 0x04), |
751 | REG_SEQ0(0x805a, 0x00), |
752 | REG_SEQ0(0x805b, 0x00), |
753 | REG_SEQ0(0x805c, 0x00), |
754 | REG_SEQ0(0x805d, 0x00), |
755 | REG_SEQ0(0x805a, 0x01), |
756 | REG_SEQ0(0x805a, 0x00), |
757 | }; |
758 | |
759 | ret = request_firmware(fw: &fw, FW_FILE, device: lt9611uxc->dev); |
760 | if (ret < 0) |
761 | return ret; |
762 | |
763 | dev_info(lt9611uxc->dev, "Updating firmware\n" ); |
764 | lt9611uxc_lock(lt9611uxc); |
765 | |
766 | regmap_multi_reg_write(map: lt9611uxc->regmap, regs: seq_setup, ARRAY_SIZE(seq_setup)); |
767 | |
768 | /* |
769 | * Need erase block 2 timess here. Sometimes, block erase can fail. |
770 | * This is a workaroud. |
771 | */ |
772 | regmap_multi_reg_write(map: lt9611uxc->regmap, regs: seq_block_erase, ARRAY_SIZE(seq_block_erase)); |
773 | msleep(msecs: 3000); |
774 | regmap_multi_reg_write(map: lt9611uxc->regmap, regs: seq_block_erase, ARRAY_SIZE(seq_block_erase)); |
775 | msleep(msecs: 3000); |
776 | |
777 | for (offset = 0, remain = fw->size; |
778 | remain >= LT9611UXC_FW_PAGE_SIZE; |
779 | offset += LT9611UXC_FW_PAGE_SIZE, remain -= LT9611UXC_FW_PAGE_SIZE) |
780 | lt9611uxc_firmware_write_page(lt9611uxc, addr: offset, buf: fw->data + offset); |
781 | |
782 | if (remain > 0) { |
783 | char buf[LT9611UXC_FW_PAGE_SIZE]; |
784 | |
785 | memset(buf, 0xff, LT9611UXC_FW_PAGE_SIZE); |
786 | memcpy(buf, fw->data + offset, remain); |
787 | lt9611uxc_firmware_write_page(lt9611uxc, addr: offset, buf); |
788 | } |
789 | msleep(msecs: 20); |
790 | |
791 | readbuf = lt9611uxc_firmware_read(lt9611uxc, size: fw->size); |
792 | if (!readbuf) { |
793 | ret = -ENOMEM; |
794 | goto out; |
795 | } |
796 | |
797 | if (!memcmp(p: readbuf, q: fw->data, size: fw->size)) { |
798 | dev_err(lt9611uxc->dev, "Firmware update failed\n" ); |
799 | print_hex_dump(KERN_ERR, prefix_str: "fw: " , prefix_type: DUMP_PREFIX_OFFSET, rowsize: 16, groupsize: 1, buf: readbuf, len: fw->size, ascii: false); |
800 | ret = -EINVAL; |
801 | } else { |
802 | dev_info(lt9611uxc->dev, "Firmware updates successfully\n" ); |
803 | ret = 0; |
804 | } |
805 | kfree(objp: readbuf); |
806 | |
807 | out: |
808 | lt9611uxc_unlock(lt9611uxc); |
809 | lt9611uxc_reset(lt9611uxc); |
810 | release_firmware(fw); |
811 | |
812 | return ret; |
813 | } |
814 | |
815 | static ssize_t lt9611uxc_firmware_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) |
816 | { |
817 | struct lt9611uxc *lt9611uxc = dev_get_drvdata(dev); |
818 | int ret; |
819 | |
820 | ret = lt9611uxc_firmware_update(lt9611uxc); |
821 | if (ret < 0) |
822 | return ret; |
823 | return len; |
824 | } |
825 | |
826 | static ssize_t lt9611uxc_firmware_show(struct device *dev, struct device_attribute *attr, char *buf) |
827 | { |
828 | struct lt9611uxc *lt9611uxc = dev_get_drvdata(dev); |
829 | |
830 | return sysfs_emit(buf, fmt: "%02x\n" , lt9611uxc->fw_version); |
831 | } |
832 | |
833 | static DEVICE_ATTR_RW(lt9611uxc_firmware); |
834 | |
835 | static struct attribute *lt9611uxc_attrs[] = { |
836 | &dev_attr_lt9611uxc_firmware.attr, |
837 | NULL, |
838 | }; |
839 | |
840 | static const struct attribute_group lt9611uxc_attr_group = { |
841 | .attrs = lt9611uxc_attrs, |
842 | }; |
843 | |
844 | static const struct attribute_group *lt9611uxc_attr_groups[] = { |
845 | <9611uxc_attr_group, |
846 | NULL, |
847 | }; |
848 | |
849 | static int lt9611uxc_probe(struct i2c_client *client) |
850 | { |
851 | struct lt9611uxc *lt9611uxc; |
852 | struct device *dev = &client->dev; |
853 | int ret; |
854 | bool fw_updated = false; |
855 | |
856 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_I2C)) { |
857 | dev_err(dev, "device doesn't support I2C\n" ); |
858 | return -ENODEV; |
859 | } |
860 | |
861 | lt9611uxc = devm_kzalloc(dev, size: sizeof(*lt9611uxc), GFP_KERNEL); |
862 | if (!lt9611uxc) |
863 | return -ENOMEM; |
864 | |
865 | lt9611uxc->dev = dev; |
866 | lt9611uxc->client = client; |
867 | mutex_init(<9611uxc->ocm_lock); |
868 | |
869 | lt9611uxc->regmap = devm_regmap_init_i2c(client, <9611uxc_regmap_config); |
870 | if (IS_ERR(ptr: lt9611uxc->regmap)) { |
871 | dev_err(lt9611uxc->dev, "regmap i2c init failed\n" ); |
872 | return PTR_ERR(ptr: lt9611uxc->regmap); |
873 | } |
874 | |
875 | ret = lt9611uxc_parse_dt(dev, lt9611uxc); |
876 | if (ret) { |
877 | dev_err(dev, "failed to parse device tree\n" ); |
878 | return ret; |
879 | } |
880 | |
881 | ret = lt9611uxc_gpio_init(lt9611uxc); |
882 | if (ret < 0) |
883 | goto err_of_put; |
884 | |
885 | ret = lt9611uxc_regulator_init(lt9611uxc); |
886 | if (ret < 0) |
887 | goto err_of_put; |
888 | |
889 | lt9611uxc_assert_5v(lt9611uxc); |
890 | |
891 | ret = lt9611uxc_regulator_enable(lt9611uxc); |
892 | if (ret) |
893 | goto err_of_put; |
894 | |
895 | lt9611uxc_reset(lt9611uxc); |
896 | |
897 | ret = lt9611uxc_read_device_rev(lt9611uxc); |
898 | if (ret) { |
899 | dev_err(dev, "failed to read chip rev\n" ); |
900 | goto err_disable_regulators; |
901 | } |
902 | |
903 | retry: |
904 | ret = lt9611uxc_read_version(lt9611uxc); |
905 | if (ret < 0) { |
906 | dev_err(dev, "failed to read FW version\n" ); |
907 | goto err_disable_regulators; |
908 | } else if (ret == 0) { |
909 | if (!fw_updated) { |
910 | fw_updated = true; |
911 | dev_err(dev, "FW version 0, enforcing firmware update\n" ); |
912 | ret = lt9611uxc_firmware_update(lt9611uxc); |
913 | if (ret < 0) |
914 | goto err_disable_regulators; |
915 | else |
916 | goto retry; |
917 | } else { |
918 | dev_err(dev, "FW version 0, update failed\n" ); |
919 | ret = -EOPNOTSUPP; |
920 | goto err_disable_regulators; |
921 | } |
922 | } else if (ret < 0x40) { |
923 | dev_info(dev, "FW version 0x%x, HPD not supported\n" , ret); |
924 | } else { |
925 | lt9611uxc->hpd_supported = true; |
926 | } |
927 | lt9611uxc->fw_version = ret; |
928 | |
929 | init_waitqueue_head(<9611uxc->wq); |
930 | INIT_WORK(<9611uxc->work, lt9611uxc_hpd_work); |
931 | |
932 | ret = request_threaded_irq(irq: client->irq, NULL, |
933 | thread_fn: lt9611uxc_irq_thread_handler, |
934 | IRQF_ONESHOT, name: "lt9611uxc" , dev: lt9611uxc); |
935 | if (ret) { |
936 | dev_err(dev, "failed to request irq\n" ); |
937 | goto err_disable_regulators; |
938 | } |
939 | |
940 | i2c_set_clientdata(client, data: lt9611uxc); |
941 | |
942 | lt9611uxc->bridge.funcs = <9611uxc_bridge_funcs; |
943 | lt9611uxc->bridge.of_node = client->dev.of_node; |
944 | lt9611uxc->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; |
945 | if (lt9611uxc->hpd_supported) |
946 | lt9611uxc->bridge.ops |= DRM_BRIDGE_OP_HPD; |
947 | lt9611uxc->bridge.type = DRM_MODE_CONNECTOR_HDMIA; |
948 | |
949 | drm_bridge_add(bridge: <9611uxc->bridge); |
950 | |
951 | /* Attach primary DSI */ |
952 | lt9611uxc->dsi0 = lt9611uxc_attach_dsi(lt9611uxc, dsi_node: lt9611uxc->dsi0_node); |
953 | if (IS_ERR(ptr: lt9611uxc->dsi0)) { |
954 | ret = PTR_ERR(ptr: lt9611uxc->dsi0); |
955 | goto err_remove_bridge; |
956 | } |
957 | |
958 | /* Attach secondary DSI, if specified */ |
959 | if (lt9611uxc->dsi1_node) { |
960 | lt9611uxc->dsi1 = lt9611uxc_attach_dsi(lt9611uxc, dsi_node: lt9611uxc->dsi1_node); |
961 | if (IS_ERR(ptr: lt9611uxc->dsi1)) { |
962 | ret = PTR_ERR(ptr: lt9611uxc->dsi1); |
963 | goto err_remove_bridge; |
964 | } |
965 | } |
966 | |
967 | return lt9611uxc_audio_init(dev, lt9611uxc); |
968 | |
969 | err_remove_bridge: |
970 | free_irq(client->irq, lt9611uxc); |
971 | cancel_work_sync(work: <9611uxc->work); |
972 | drm_bridge_remove(bridge: <9611uxc->bridge); |
973 | |
974 | err_disable_regulators: |
975 | regulator_bulk_disable(ARRAY_SIZE(lt9611uxc->supplies), consumers: lt9611uxc->supplies); |
976 | |
977 | err_of_put: |
978 | of_node_put(node: lt9611uxc->dsi1_node); |
979 | of_node_put(node: lt9611uxc->dsi0_node); |
980 | |
981 | return ret; |
982 | } |
983 | |
984 | static void lt9611uxc_remove(struct i2c_client *client) |
985 | { |
986 | struct lt9611uxc *lt9611uxc = i2c_get_clientdata(client); |
987 | |
988 | free_irq(client->irq, lt9611uxc); |
989 | cancel_work_sync(work: <9611uxc->work); |
990 | lt9611uxc_audio_exit(lt9611uxc); |
991 | drm_bridge_remove(bridge: <9611uxc->bridge); |
992 | |
993 | mutex_destroy(lock: <9611uxc->ocm_lock); |
994 | |
995 | regulator_bulk_disable(ARRAY_SIZE(lt9611uxc->supplies), consumers: lt9611uxc->supplies); |
996 | |
997 | of_node_put(node: lt9611uxc->dsi1_node); |
998 | of_node_put(node: lt9611uxc->dsi0_node); |
999 | } |
1000 | |
1001 | static struct i2c_device_id lt9611uxc_id[] = { |
1002 | { "lontium,lt9611uxc" , 0 }, |
1003 | { /* sentinel */ } |
1004 | }; |
1005 | |
1006 | static const struct of_device_id lt9611uxc_match_table[] = { |
1007 | { .compatible = "lontium,lt9611uxc" }, |
1008 | { /* sentinel */ } |
1009 | }; |
1010 | MODULE_DEVICE_TABLE(of, lt9611uxc_match_table); |
1011 | |
1012 | static struct i2c_driver lt9611uxc_driver = { |
1013 | .driver = { |
1014 | .name = "lt9611uxc" , |
1015 | .of_match_table = lt9611uxc_match_table, |
1016 | .dev_groups = lt9611uxc_attr_groups, |
1017 | }, |
1018 | .probe = lt9611uxc_probe, |
1019 | .remove = lt9611uxc_remove, |
1020 | .id_table = lt9611uxc_id, |
1021 | }; |
1022 | module_i2c_driver(lt9611uxc_driver); |
1023 | |
1024 | MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>" ); |
1025 | MODULE_LICENSE("GPL v2" ); |
1026 | |
1027 | MODULE_FIRMWARE(FW_FILE); |
1028 | |