Lines Matching full:lt9611uxc
35 struct lt9611uxc { struct
119 static struct lt9611uxc *bridge_to_lt9611uxc(struct drm_bridge *bridge) in bridge_to_lt9611uxc()
121 return container_of(bridge, struct lt9611uxc, bridge); in bridge_to_lt9611uxc()
124 static void lt9611uxc_lock(struct lt9611uxc *lt9611uxc) in lt9611uxc_lock() argument
126 mutex_lock(<9611uxc->ocm_lock); in lt9611uxc_lock()
127 regmap_write(lt9611uxc->regmap, 0x80ee, 0x01); in lt9611uxc_lock()
130 static void lt9611uxc_unlock(struct lt9611uxc *lt9611uxc) in lt9611uxc_unlock() argument
132 regmap_write(lt9611uxc->regmap, 0x80ee, 0x00); in lt9611uxc_unlock()
134 mutex_unlock(<9611uxc->ocm_lock); in lt9611uxc_unlock()
139 struct lt9611uxc *lt9611uxc = dev_id; in lt9611uxc_irq_thread_handler() local
143 lt9611uxc_lock(lt9611uxc); in lt9611uxc_irq_thread_handler()
145 regmap_read(lt9611uxc->regmap, 0xb022, &irq_status); in lt9611uxc_irq_thread_handler()
146 regmap_read(lt9611uxc->regmap, 0xb023, &hpd_status); in lt9611uxc_irq_thread_handler()
148 regmap_write(lt9611uxc->regmap, 0xb022, 0); in lt9611uxc_irq_thread_handler()
151 lt9611uxc->edid_read = !!(hpd_status & BIT(0)); in lt9611uxc_irq_thread_handler()
152 wake_up_all(<9611uxc->wq); in lt9611uxc_irq_thread_handler()
156 lt9611uxc->hdmi_connected = hpd_status & BIT(1); in lt9611uxc_irq_thread_handler()
157 schedule_work(<9611uxc->work); in lt9611uxc_irq_thread_handler()
160 lt9611uxc_unlock(lt9611uxc); in lt9611uxc_irq_thread_handler()
167 struct lt9611uxc *lt9611uxc = container_of(work, struct lt9611uxc, work); in lt9611uxc_hpd_work() local
170 mutex_lock(<9611uxc->ocm_lock); in lt9611uxc_hpd_work()
171 connected = lt9611uxc->hdmi_connected; in lt9611uxc_hpd_work()
172 mutex_unlock(<9611uxc->ocm_lock); in lt9611uxc_hpd_work()
174 drm_bridge_hpd_notify(<9611uxc->bridge, in lt9611uxc_hpd_work()
180 static void lt9611uxc_reset(struct lt9611uxc *lt9611uxc) in lt9611uxc_reset() argument
182 gpiod_set_value_cansleep(lt9611uxc->reset_gpio, 1); in lt9611uxc_reset()
185 gpiod_set_value_cansleep(lt9611uxc->reset_gpio, 0); in lt9611uxc_reset()
188 gpiod_set_value_cansleep(lt9611uxc->reset_gpio, 1); in lt9611uxc_reset()
192 static void lt9611uxc_assert_5v(struct lt9611uxc *lt9611uxc) in lt9611uxc_assert_5v() argument
194 if (!lt9611uxc->enable_gpio) in lt9611uxc_assert_5v()
197 gpiod_set_value_cansleep(lt9611uxc->enable_gpio, 1); in lt9611uxc_assert_5v()
201 static int lt9611uxc_regulator_init(struct lt9611uxc *lt9611uxc) in lt9611uxc_regulator_init() argument
205 lt9611uxc->supplies[0].supply = "vdd"; in lt9611uxc_regulator_init()
206 lt9611uxc->supplies[1].supply = "vcc"; in lt9611uxc_regulator_init()
208 ret = devm_regulator_bulk_get(lt9611uxc->dev, 2, lt9611uxc->supplies); in lt9611uxc_regulator_init()
212 return regulator_set_load(lt9611uxc->supplies[0].consumer, 200000); in lt9611uxc_regulator_init()
215 static int lt9611uxc_regulator_enable(struct lt9611uxc *lt9611uxc) in lt9611uxc_regulator_enable() argument
219 ret = regulator_enable(lt9611uxc->supplies[0].consumer); in lt9611uxc_regulator_enable()
225 ret = regulator_enable(lt9611uxc->supplies[1].consumer); in lt9611uxc_regulator_enable()
227 regulator_disable(lt9611uxc->supplies[0].consumer); in lt9611uxc_regulator_enable()
249 static struct mipi_dsi_device *lt9611uxc_attach_dsi(struct lt9611uxc *lt9611uxc, in lt9611uxc_attach_dsi() argument
252 const struct mipi_dsi_device_info info = { "lt9611uxc", 0, NULL }; in lt9611uxc_attach_dsi()
255 struct device *dev = lt9611uxc->dev; in lt9611uxc_attach_dsi()
285 struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge); in lt9611uxc_bridge_attach() local
287 return drm_bridge_attach(bridge->encoder, lt9611uxc->next_bridge, in lt9611uxc_bridge_attach()
303 static void lt9611uxc_video_setup(struct lt9611uxc *lt9611uxc, in lt9611uxc_video_setup() argument
320 regmap_write(lt9611uxc->regmap, 0xd00d, (u8)(v_total / 256)); in lt9611uxc_video_setup()
321 regmap_write(lt9611uxc->regmap, 0xd00e, (u8)(v_total % 256)); in lt9611uxc_video_setup()
323 regmap_write(lt9611uxc->regmap, 0xd00f, (u8)(vactive / 256)); in lt9611uxc_video_setup()
324 regmap_write(lt9611uxc->regmap, 0xd010, (u8)(vactive % 256)); in lt9611uxc_video_setup()
326 regmap_write(lt9611uxc->regmap, 0xd011, (u8)(h_total / 256)); in lt9611uxc_video_setup()
327 regmap_write(lt9611uxc->regmap, 0xd012, (u8)(h_total % 256)); in lt9611uxc_video_setup()
329 regmap_write(lt9611uxc->regmap, 0xd013, (u8)(hactive / 256)); in lt9611uxc_video_setup()
330 regmap_write(lt9611uxc->regmap, 0xd014, (u8)(hactive % 256)); in lt9611uxc_video_setup()
332 regmap_write(lt9611uxc->regmap, 0xd015, (u8)(vsync_len % 256)); in lt9611uxc_video_setup()
334 regmap_update_bits(lt9611uxc->regmap, 0xd016, 0xf, (u8)(hsync_len / 256)); in lt9611uxc_video_setup()
335 regmap_write(lt9611uxc->regmap, 0xd017, (u8)(hsync_len % 256)); in lt9611uxc_video_setup()
337 regmap_update_bits(lt9611uxc->regmap, 0xd018, 0xf, (u8)(vfront_porch / 256)); in lt9611uxc_video_setup()
338 regmap_write(lt9611uxc->regmap, 0xd019, (u8)(vfront_porch % 256)); in lt9611uxc_video_setup()
340 regmap_update_bits(lt9611uxc->regmap, 0xd01a, 0xf, (u8)(hfront_porch / 256)); in lt9611uxc_video_setup()
341 regmap_write(lt9611uxc->regmap, 0xd01b, (u8)(hfront_porch % 256)); in lt9611uxc_video_setup()
348 struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge); in lt9611uxc_bridge_mode_set() local
350 lt9611uxc_lock(lt9611uxc); in lt9611uxc_bridge_mode_set()
351 lt9611uxc_video_setup(lt9611uxc, mode); in lt9611uxc_bridge_mode_set()
352 lt9611uxc_unlock(lt9611uxc); in lt9611uxc_bridge_mode_set()
357 struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge); in lt9611uxc_bridge_detect() local
362 lt9611uxc_lock(lt9611uxc); in lt9611uxc_bridge_detect()
364 if (lt9611uxc->hpd_supported) { in lt9611uxc_bridge_detect()
365 ret = regmap_read(lt9611uxc->regmap, 0xb023, ®_val); in lt9611uxc_bridge_detect()
368 dev_err(lt9611uxc->dev, "failed to read hpd status: %d\n", ret); in lt9611uxc_bridge_detect()
372 lt9611uxc->hdmi_connected = connected; in lt9611uxc_bridge_detect()
374 lt9611uxc_unlock(lt9611uxc); in lt9611uxc_bridge_detect()
380 static int lt9611uxc_wait_for_edid(struct lt9611uxc *lt9611uxc) in lt9611uxc_wait_for_edid() argument
382 return wait_event_interruptible_timeout(lt9611uxc->wq, lt9611uxc->edid_read, in lt9611uxc_wait_for_edid()
388 struct lt9611uxc *lt9611uxc = data; in lt9611uxc_get_edid_block() local
397 lt9611uxc_lock(lt9611uxc); in lt9611uxc_get_edid_block()
399 regmap_write(lt9611uxc->regmap, 0xb00b, 0x10); in lt9611uxc_get_edid_block()
401 regmap_write(lt9611uxc->regmap, 0xb00a, block * EDID_BLOCK_SIZE); in lt9611uxc_get_edid_block()
403 ret = regmap_noinc_read(lt9611uxc->regmap, 0xb0b0, buf, len); in lt9611uxc_get_edid_block()
405 dev_err(lt9611uxc->dev, "edid read failed: %d\n", ret); in lt9611uxc_get_edid_block()
407 lt9611uxc_unlock(lt9611uxc); in lt9611uxc_get_edid_block()
415 struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge); in lt9611uxc_bridge_edid_read() local
418 ret = lt9611uxc_wait_for_edid(lt9611uxc); in lt9611uxc_bridge_edid_read()
420 dev_err(lt9611uxc->dev, "wait for EDID failed: %d\n", ret); in lt9611uxc_bridge_edid_read()
423 dev_err(lt9611uxc->dev, "wait for EDID timeout\n"); in lt9611uxc_bridge_edid_read()
427 return drm_edid_read_custom(connector, lt9611uxc_get_edid_block, lt9611uxc); in lt9611uxc_bridge_edid_read()
439 struct lt9611uxc *lt9611uxc) in lt9611uxc_parse_dt() argument
441 lt9611uxc->dsi0_node = of_graph_get_remote_node(dev->of_node, 0, -1); in lt9611uxc_parse_dt()
442 if (!lt9611uxc->dsi0_node) { in lt9611uxc_parse_dt()
443 dev_err(lt9611uxc->dev, "failed to get remote node for primary dsi\n"); in lt9611uxc_parse_dt()
447 lt9611uxc->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1); in lt9611uxc_parse_dt()
449 return drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, <9611uxc->next_bridge); in lt9611uxc_parse_dt()
452 static int lt9611uxc_gpio_init(struct lt9611uxc *lt9611uxc) in lt9611uxc_gpio_init() argument
454 struct device *dev = lt9611uxc->dev; in lt9611uxc_gpio_init()
456 lt9611uxc->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); in lt9611uxc_gpio_init()
457 if (IS_ERR(lt9611uxc->reset_gpio)) { in lt9611uxc_gpio_init()
459 return PTR_ERR(lt9611uxc->reset_gpio); in lt9611uxc_gpio_init()
462 lt9611uxc->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); in lt9611uxc_gpio_init()
463 if (IS_ERR(lt9611uxc->enable_gpio)) { in lt9611uxc_gpio_init()
465 return PTR_ERR(lt9611uxc->enable_gpio); in lt9611uxc_gpio_init()
471 static int lt9611uxc_read_device_rev(struct lt9611uxc *lt9611uxc) in lt9611uxc_read_device_rev() argument
476 lt9611uxc_lock(lt9611uxc); in lt9611uxc_read_device_rev()
478 ret = regmap_read(lt9611uxc->regmap, 0x8100, &rev0); in lt9611uxc_read_device_rev()
479 ret |= regmap_read(lt9611uxc->regmap, 0x8101, &rev1); in lt9611uxc_read_device_rev()
480 ret |= regmap_read(lt9611uxc->regmap, 0x8102, &rev2); in lt9611uxc_read_device_rev()
482 dev_err(lt9611uxc->dev, "failed to read revision: %d\n", ret); in lt9611uxc_read_device_rev()
484 dev_info(lt9611uxc->dev, "LT9611 revision: 0x%02x.%02x.%02x\n", rev0, rev1, rev2); in lt9611uxc_read_device_rev()
486 lt9611uxc_unlock(lt9611uxc); in lt9611uxc_read_device_rev()
491 static int lt9611uxc_read_version(struct lt9611uxc *lt9611uxc) in lt9611uxc_read_version() argument
496 lt9611uxc_lock(lt9611uxc); in lt9611uxc_read_version()
498 ret = regmap_read(lt9611uxc->regmap, 0xb021, &rev); in lt9611uxc_read_version()
500 dev_err(lt9611uxc->dev, "failed to read revision: %d\n", ret); in lt9611uxc_read_version()
502 dev_info(lt9611uxc->dev, "LT9611 version: 0x%02x\n", rev); in lt9611uxc_read_version()
504 lt9611uxc_unlock(lt9611uxc); in lt9611uxc_read_version()
514 * LT9611UXC will automatically detect rate and sample size, so no need in lt9611uxc_hdmi_hw_params()
550 static int lt9611uxc_audio_init(struct device *dev, struct lt9611uxc *lt9611uxc) in lt9611uxc_audio_init() argument
556 .data = lt9611uxc, in lt9611uxc_audio_init()
559 lt9611uxc->audio_pdev = in lt9611uxc_audio_init()
564 return PTR_ERR_OR_ZERO(lt9611uxc->audio_pdev); in lt9611uxc_audio_init()
567 static void lt9611uxc_audio_exit(struct lt9611uxc *lt9611uxc) in lt9611uxc_audio_exit() argument
569 if (lt9611uxc->audio_pdev) { in lt9611uxc_audio_exit()
570 platform_device_unregister(lt9611uxc->audio_pdev); in lt9611uxc_audio_exit()
571 lt9611uxc->audio_pdev = NULL; in lt9611uxc_audio_exit()
576 static void lt9611uxc_firmware_write_page(struct lt9611uxc *lt9611uxc, u16 addr, const u8 *buf) in lt9611uxc_firmware_write_page() argument
596 regmap_write(lt9611uxc->regmap, 0x8108, 0xbf); in lt9611uxc_firmware_write_page()
598 regmap_write(lt9611uxc->regmap, 0x8108, 0xff); in lt9611uxc_firmware_write_page()
600 regmap_multi_reg_write(lt9611uxc->regmap, seq_write_prepare, ARRAY_SIZE(seq_write_prepare)); in lt9611uxc_firmware_write_page()
601 regmap_noinc_write(lt9611uxc->regmap, 0x8059, buf, LT9611UXC_FW_PAGE_SIZE); in lt9611uxc_firmware_write_page()
602 regmap_multi_reg_write(lt9611uxc->regmap, seq_write_addr, ARRAY_SIZE(seq_write_addr)); in lt9611uxc_firmware_write_page()
606 static void lt9611uxc_firmware_read_page(struct lt9611uxc *lt9611uxc, u16 addr, char *buf) in lt9611uxc_firmware_read_page() argument
619 regmap_multi_reg_write(lt9611uxc->regmap, seq_read_page, ARRAY_SIZE(seq_read_page)); in lt9611uxc_firmware_read_page()
620 regmap_noinc_read(lt9611uxc->regmap, 0x805f, buf, LT9611UXC_FW_PAGE_SIZE); in lt9611uxc_firmware_read_page()
623 static char *lt9611uxc_firmware_read(struct lt9611uxc *lt9611uxc, size_t size) in lt9611uxc_firmware_read() argument
637 regmap_multi_reg_write(lt9611uxc->regmap, seq_read_setup, ARRAY_SIZE(seq_read_setup)); in lt9611uxc_firmware_read()
642 lt9611uxc_firmware_read_page(lt9611uxc, offset, &readbuf[offset]); in lt9611uxc_firmware_read()
647 static int lt9611uxc_firmware_update(struct lt9611uxc *lt9611uxc) in lt9611uxc_firmware_update() argument
674 ret = request_firmware(&fw, FW_FILE, lt9611uxc->dev); in lt9611uxc_firmware_update()
678 dev_info(lt9611uxc->dev, "Updating firmware\n"); in lt9611uxc_firmware_update()
679 lt9611uxc_lock(lt9611uxc); in lt9611uxc_firmware_update()
681 regmap_multi_reg_write(lt9611uxc->regmap, seq_setup, ARRAY_SIZE(seq_setup)); in lt9611uxc_firmware_update()
687 regmap_multi_reg_write(lt9611uxc->regmap, seq_block_erase, ARRAY_SIZE(seq_block_erase)); in lt9611uxc_firmware_update()
689 regmap_multi_reg_write(lt9611uxc->regmap, seq_block_erase, ARRAY_SIZE(seq_block_erase)); in lt9611uxc_firmware_update()
695 lt9611uxc_firmware_write_page(lt9611uxc, offset, fw->data + offset); in lt9611uxc_firmware_update()
702 lt9611uxc_firmware_write_page(lt9611uxc, offset, buf); in lt9611uxc_firmware_update()
706 readbuf = lt9611uxc_firmware_read(lt9611uxc, fw->size); in lt9611uxc_firmware_update()
713 dev_err(lt9611uxc->dev, "Firmware update failed\n"); in lt9611uxc_firmware_update()
717 dev_info(lt9611uxc->dev, "Firmware updates successfully\n"); in lt9611uxc_firmware_update()
723 lt9611uxc_unlock(lt9611uxc); in lt9611uxc_firmware_update()
724 lt9611uxc_reset(lt9611uxc); in lt9611uxc_firmware_update()
732 struct lt9611uxc *lt9611uxc = dev_get_drvdata(dev); in lt9611uxc_firmware_store() local
735 ret = lt9611uxc_firmware_update(lt9611uxc); in lt9611uxc_firmware_store()
743 struct lt9611uxc *lt9611uxc = dev_get_drvdata(dev); in lt9611uxc_firmware_show() local
745 return sysfs_emit(buf, "%02x\n", lt9611uxc->fw_version); in lt9611uxc_firmware_show()
766 struct lt9611uxc *lt9611uxc; in lt9611uxc_probe() local
776 lt9611uxc = devm_kzalloc(dev, sizeof(*lt9611uxc), GFP_KERNEL); in lt9611uxc_probe()
777 if (!lt9611uxc) in lt9611uxc_probe()
780 lt9611uxc->dev = dev; in lt9611uxc_probe()
781 lt9611uxc->client = client; in lt9611uxc_probe()
782 mutex_init(<9611uxc->ocm_lock); in lt9611uxc_probe()
784 lt9611uxc->regmap = devm_regmap_init_i2c(client, <9611uxc_regmap_config); in lt9611uxc_probe()
785 if (IS_ERR(lt9611uxc->regmap)) { in lt9611uxc_probe()
786 dev_err(lt9611uxc->dev, "regmap i2c init failed\n"); in lt9611uxc_probe()
787 return PTR_ERR(lt9611uxc->regmap); in lt9611uxc_probe()
790 ret = lt9611uxc_parse_dt(dev, lt9611uxc); in lt9611uxc_probe()
796 ret = lt9611uxc_gpio_init(lt9611uxc); in lt9611uxc_probe()
800 ret = lt9611uxc_regulator_init(lt9611uxc); in lt9611uxc_probe()
804 lt9611uxc_assert_5v(lt9611uxc); in lt9611uxc_probe()
806 ret = lt9611uxc_regulator_enable(lt9611uxc); in lt9611uxc_probe()
810 lt9611uxc_reset(lt9611uxc); in lt9611uxc_probe()
812 ret = lt9611uxc_read_device_rev(lt9611uxc); in lt9611uxc_probe()
819 ret = lt9611uxc_read_version(lt9611uxc); in lt9611uxc_probe()
827 ret = lt9611uxc_firmware_update(lt9611uxc); in lt9611uxc_probe()
840 lt9611uxc->hpd_supported = true; in lt9611uxc_probe()
842 lt9611uxc->fw_version = ret; in lt9611uxc_probe()
844 init_waitqueue_head(<9611uxc->wq); in lt9611uxc_probe()
845 INIT_WORK(<9611uxc->work, lt9611uxc_hpd_work); in lt9611uxc_probe()
849 IRQF_ONESHOT, "lt9611uxc", lt9611uxc); in lt9611uxc_probe()
855 i2c_set_clientdata(client, lt9611uxc); in lt9611uxc_probe()
857 lt9611uxc->bridge.funcs = <9611uxc_bridge_funcs; in lt9611uxc_probe()
858 lt9611uxc->bridge.of_node = client->dev.of_node; in lt9611uxc_probe()
859 lt9611uxc->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; in lt9611uxc_probe()
860 if (lt9611uxc->hpd_supported) in lt9611uxc_probe()
861 lt9611uxc->bridge.ops |= DRM_BRIDGE_OP_HPD; in lt9611uxc_probe()
862 lt9611uxc->bridge.type = DRM_MODE_CONNECTOR_HDMIA; in lt9611uxc_probe()
864 drm_bridge_add(<9611uxc->bridge); in lt9611uxc_probe()
867 lt9611uxc->dsi0 = lt9611uxc_attach_dsi(lt9611uxc, lt9611uxc->dsi0_node); in lt9611uxc_probe()
868 if (IS_ERR(lt9611uxc->dsi0)) { in lt9611uxc_probe()
869 ret = PTR_ERR(lt9611uxc->dsi0); in lt9611uxc_probe()
874 if (lt9611uxc->dsi1_node) { in lt9611uxc_probe()
875 lt9611uxc->dsi1 = lt9611uxc_attach_dsi(lt9611uxc, lt9611uxc->dsi1_node); in lt9611uxc_probe()
876 if (IS_ERR(lt9611uxc->dsi1)) { in lt9611uxc_probe()
877 ret = PTR_ERR(lt9611uxc->dsi1); in lt9611uxc_probe()
882 return lt9611uxc_audio_init(dev, lt9611uxc); in lt9611uxc_probe()
885 free_irq(client->irq, lt9611uxc); in lt9611uxc_probe()
886 cancel_work_sync(<9611uxc->work); in lt9611uxc_probe()
887 drm_bridge_remove(<9611uxc->bridge); in lt9611uxc_probe()
890 regulator_bulk_disable(ARRAY_SIZE(lt9611uxc->supplies), lt9611uxc->supplies); in lt9611uxc_probe()
893 of_node_put(lt9611uxc->dsi1_node); in lt9611uxc_probe()
894 of_node_put(lt9611uxc->dsi0_node); in lt9611uxc_probe()
901 struct lt9611uxc *lt9611uxc = i2c_get_clientdata(client); in lt9611uxc_remove() local
903 free_irq(client->irq, lt9611uxc); in lt9611uxc_remove()
904 cancel_work_sync(<9611uxc->work); in lt9611uxc_remove()
905 lt9611uxc_audio_exit(lt9611uxc); in lt9611uxc_remove()
906 drm_bridge_remove(<9611uxc->bridge); in lt9611uxc_remove()
908 mutex_destroy(<9611uxc->ocm_lock); in lt9611uxc_remove()
910 regulator_bulk_disable(ARRAY_SIZE(lt9611uxc->supplies), lt9611uxc->supplies); in lt9611uxc_remove()
912 of_node_put(lt9611uxc->dsi1_node); in lt9611uxc_remove()
913 of_node_put(lt9611uxc->dsi0_node); in lt9611uxc_remove()
917 { "lontium,lt9611uxc", 0 },
922 { .compatible = "lontium,lt9611uxc" },
929 .name = "lt9611uxc",
940 MODULE_DESCRIPTION("Lontium LT9611UXC DSI/HDMI bridge driver");