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