Path: blob/master/drivers/gpu/drm/bridge/lontium-lt9611.c
51650 views
// SPDX-License-Identifier: GPL-2.01/*2* Copyright (c) 2018, The Linux Foundation. All rights reserved.3* Copyright (c) 2019-2020. Linaro Limited.4*/56#include <linux/gpio/consumer.h>7#include <linux/i2c.h>8#include <linux/interrupt.h>9#include <linux/media-bus-format.h>10#include <linux/module.h>11#include <linux/of_graph.h>12#include <linux/platform_device.h>13#include <linux/regmap.h>14#include <linux/regulator/consumer.h>1516#include <sound/hdmi-codec.h>1718#include <drm/drm_atomic_helper.h>19#include <drm/drm_bridge.h>20#include <drm/drm_edid.h>21#include <drm/drm_mipi_dsi.h>22#include <drm/drm_of.h>23#include <drm/drm_print.h>24#include <drm/drm_probe_helper.h>25#include <drm/display/drm_hdmi_helper.h>26#include <drm/display/drm_hdmi_state_helper.h>2728#define EDID_SEG_SIZE 25629#define EDID_LEN 3230#define EDID_LOOP 831#define KEY_DDC_ACCS_DONE 0x0232#define DDC_NO_ACK 0x503334#define LT9611_4LANES 03536struct lt9611 {37struct device *dev;38struct drm_bridge bridge;39struct drm_bridge *next_bridge;4041struct regmap *regmap;4243struct device_node *dsi0_node;44struct device_node *dsi1_node;45struct mipi_dsi_device *dsi0;46struct mipi_dsi_device *dsi1;4748bool ac_mode;4950struct gpio_desc *reset_gpio;51struct gpio_desc *enable_gpio;5253bool power_on;54bool sleep;5556struct regulator_bulk_data supplies[2];5758struct i2c_client *client;5960enum drm_connector_status status;6162u8 edid_buf[EDID_SEG_SIZE];63};6465#define LT9611_PAGE_CONTROL 0xff6667static const struct regmap_range_cfg lt9611_ranges[] = {68{69.name = "register_range",70.range_min = 0,71.range_max = 0x85ff,72.selector_reg = LT9611_PAGE_CONTROL,73.selector_mask = 0xff,74.selector_shift = 0,75.window_start = 0,76.window_len = 0x100,77},78};7980static const struct regmap_config lt9611_regmap_config = {81.reg_bits = 8,82.val_bits = 8,83.max_register = 0xffff,84.ranges = lt9611_ranges,85.num_ranges = ARRAY_SIZE(lt9611_ranges),86};8788static struct lt9611 *bridge_to_lt9611(struct drm_bridge *bridge)89{90return container_of(bridge, struct lt9611, bridge);91}9293static int lt9611_mipi_input_analog(struct lt9611 *lt9611)94{95const struct reg_sequence reg_cfg[] = {96{ 0x8106, 0x40 }, /* port A rx current */97{ 0x810a, 0xfe }, /* port A ldo voltage set */98{ 0x810b, 0xbf }, /* enable port A lprx */99{ 0x8111, 0x40 }, /* port B rx current */100{ 0x8115, 0xfe }, /* port B ldo voltage set */101{ 0x8116, 0xbf }, /* enable port B lprx */102103{ 0x811c, 0x03 }, /* PortA clk lane no-LP mode */104{ 0x8120, 0x03 }, /* PortB clk lane with-LP mode */105};106107return regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg));108}109110static int lt9611_mipi_input_digital(struct lt9611 *lt9611,111const struct drm_display_mode *mode)112{113struct reg_sequence reg_cfg[] = {114{ 0x8300, LT9611_4LANES },115{ 0x830a, 0x00 },116{ 0x824f, 0x80 },117{ 0x8250, 0x10 },118{ 0x8302, 0x0a },119{ 0x8306, 0x0a },120};121122if (lt9611->dsi1_node)123reg_cfg[1].def = 0x03;124125return regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg));126}127128static void lt9611_mipi_video_setup(struct lt9611 *lt9611,129const struct drm_display_mode *mode)130{131u32 h_total, hactive, hsync_len, hfront_porch, hsync_porch;132u32 v_total, vactive, vsync_len, vfront_porch, vsync_porch;133134h_total = mode->htotal;135v_total = mode->vtotal;136137hactive = mode->hdisplay;138hsync_len = mode->hsync_end - mode->hsync_start;139hfront_porch = mode->hsync_start - mode->hdisplay;140hsync_porch = mode->htotal - mode->hsync_start;141142vactive = mode->vdisplay;143vsync_len = mode->vsync_end - mode->vsync_start;144vfront_porch = mode->vsync_start - mode->vdisplay;145vsync_porch = mode->vtotal - mode->vsync_start;146147regmap_write(lt9611->regmap, 0x830d, (u8)(v_total / 256));148regmap_write(lt9611->regmap, 0x830e, (u8)(v_total % 256));149150regmap_write(lt9611->regmap, 0x830f, (u8)(vactive / 256));151regmap_write(lt9611->regmap, 0x8310, (u8)(vactive % 256));152153regmap_write(lt9611->regmap, 0x8311, (u8)(h_total / 256));154regmap_write(lt9611->regmap, 0x8312, (u8)(h_total % 256));155156regmap_write(lt9611->regmap, 0x8313, (u8)(hactive / 256));157regmap_write(lt9611->regmap, 0x8314, (u8)(hactive % 256));158159regmap_write(lt9611->regmap, 0x8315, (u8)(vsync_len % 256));160regmap_write(lt9611->regmap, 0x8316, (u8)(hsync_len % 256));161162regmap_write(lt9611->regmap, 0x8317, (u8)(vfront_porch % 256));163164regmap_write(lt9611->regmap, 0x8318, (u8)(vsync_porch % 256));165166regmap_write(lt9611->regmap, 0x8319, (u8)(hfront_porch % 256));167168regmap_write(lt9611->regmap, 0x831a, (u8)(hsync_porch / 256) |169((hfront_porch / 256) << 4));170regmap_write(lt9611->regmap, 0x831b, (u8)(hsync_porch % 256));171}172173static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode, unsigned int postdiv)174{175unsigned int pcr_m = mode->clock * 5 * postdiv / 27000;176const struct reg_sequence reg_cfg[] = {177{ 0x830b, 0x01 },178{ 0x830c, 0x10 },179{ 0x8348, 0x00 },180{ 0x8349, 0x81 },181182/* stage 1 */183{ 0x8321, 0x4a },184{ 0x8324, 0x71 },185{ 0x8325, 0x30 },186{ 0x832a, 0x01 },187188/* stage 2 */189{ 0x834a, 0x40 },190191/* MK limit */192{ 0x832d, 0x38 },193{ 0x8331, 0x08 },194};195u8 pol = 0x10;196197if (mode->flags & DRM_MODE_FLAG_NHSYNC)198pol |= 0x2;199if (mode->flags & DRM_MODE_FLAG_NVSYNC)200pol |= 0x1;201regmap_write(lt9611->regmap, 0x831d, pol);202203regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg));204if (lt9611->dsi1_node) {205unsigned int hact = mode->hdisplay;206207hact >>= 2;208hact += 0x50;209hact = min(hact, 0x3e0U);210regmap_write(lt9611->regmap, 0x830b, hact / 256);211regmap_write(lt9611->regmap, 0x830c, hact % 256);212regmap_write(lt9611->regmap, 0x8348, hact / 256);213regmap_write(lt9611->regmap, 0x8349, hact % 256);214}215216regmap_write(lt9611->regmap, 0x8326, pcr_m);217218/* pcr rst */219regmap_write(lt9611->regmap, 0x8011, 0x5a);220regmap_write(lt9611->regmap, 0x8011, 0xfa);221}222223static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode, unsigned int *postdiv)224{225unsigned int pclk = mode->clock;226const struct reg_sequence reg_cfg[] = {227/* txpll init */228{ 0x8123, 0x40 },229{ 0x8124, 0x64 },230{ 0x8125, 0x80 },231{ 0x8126, 0x55 },232{ 0x812c, 0x37 },233{ 0x812f, 0x01 },234{ 0x8126, 0x55 },235{ 0x8127, 0x66 },236{ 0x8128, 0x88 },237{ 0x812a, 0x20 },238};239240regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg));241242if (pclk > 150000) {243regmap_write(lt9611->regmap, 0x812d, 0x88);244*postdiv = 1;245} else if (pclk > 70000) {246regmap_write(lt9611->regmap, 0x812d, 0x99);247*postdiv = 2;248} else {249regmap_write(lt9611->regmap, 0x812d, 0xaa);250*postdiv = 4;251}252253/*254* first divide pclk by 2 first255* - write divide by 64k to 19:16 bits which means shift by 17256* - write divide by 256 to 15:8 bits which means shift by 9257* - write remainder to 7:0 bits, which means shift by 1258*/259regmap_write(lt9611->regmap, 0x82e3, pclk >> 17); /* pclk[19:16] */260regmap_write(lt9611->regmap, 0x82e4, pclk >> 9); /* pclk[15:8] */261regmap_write(lt9611->regmap, 0x82e5, pclk >> 1); /* pclk[7:0] */262263regmap_write(lt9611->regmap, 0x82de, 0x20);264regmap_write(lt9611->regmap, 0x82de, 0xe0);265266regmap_write(lt9611->regmap, 0x8016, 0xf1);267regmap_write(lt9611->regmap, 0x8016, 0xf3);268269return 0;270}271272static int lt9611_read_video_check(struct lt9611 *lt9611, unsigned int reg)273{274unsigned int temp, temp2;275int ret;276277ret = regmap_read(lt9611->regmap, reg, &temp);278if (ret)279return ret;280temp <<= 8;281ret = regmap_read(lt9611->regmap, reg + 1, &temp2);282if (ret)283return ret;284285return (temp + temp2);286}287288static int lt9611_video_check(struct lt9611 *lt9611)289{290u32 v_total, vactive, hactive_a, hactive_b, h_total_sysclk;291int temp;292293/* top module video check */294295/* vactive */296temp = lt9611_read_video_check(lt9611, 0x8282);297if (temp < 0)298goto end;299vactive = temp;300301/* v_total */302temp = lt9611_read_video_check(lt9611, 0x826c);303if (temp < 0)304goto end;305v_total = temp;306307/* h_total_sysclk */308temp = lt9611_read_video_check(lt9611, 0x8286);309if (temp < 0)310goto end;311h_total_sysclk = temp;312313/* hactive_a */314temp = lt9611_read_video_check(lt9611, 0x8382);315if (temp < 0)316goto end;317hactive_a = temp / 3;318319/* hactive_b */320temp = lt9611_read_video_check(lt9611, 0x8386);321if (temp < 0)322goto end;323hactive_b = temp / 3;324325dev_info(lt9611->dev,326"video check: hactive_a=%d, hactive_b=%d, vactive=%d, v_total=%d, h_total_sysclk=%d\n",327hactive_a, hactive_b, vactive, v_total, h_total_sysclk);328329return 0;330331end:332dev_err(lt9611->dev, "read video check error\n");333return temp;334}335336static void lt9611_hdmi_tx_digital(struct lt9611 *lt9611, bool is_hdmi)337{338if (is_hdmi)339regmap_write(lt9611->regmap, 0x82d6, 0x8c);340else341regmap_write(lt9611->regmap, 0x82d6, 0x0c);342regmap_write(lt9611->regmap, 0x82d7, 0x04);343}344345static void lt9611_hdmi_tx_phy(struct lt9611 *lt9611)346{347struct reg_sequence reg_cfg[] = {348{ 0x8130, 0x6a },349{ 0x8131, 0x44 }, /* HDMI DC mode */350{ 0x8132, 0x4a },351{ 0x8133, 0x0b },352{ 0x8134, 0x00 },353{ 0x8135, 0x00 },354{ 0x8136, 0x00 },355{ 0x8137, 0x44 },356{ 0x813f, 0x0f },357{ 0x8140, 0xa0 },358{ 0x8141, 0xa0 },359{ 0x8142, 0xa0 },360{ 0x8143, 0xa0 },361{ 0x8144, 0x0a },362};363364/* HDMI AC mode */365if (lt9611->ac_mode)366reg_cfg[2].def = 0x73;367368regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg));369}370371static irqreturn_t lt9611_irq_thread_handler(int irq, void *dev_id)372{373struct lt9611 *lt9611 = dev_id;374unsigned int irq_flag0 = 0;375unsigned int irq_flag3 = 0;376377regmap_read(lt9611->regmap, 0x820f, &irq_flag3);378regmap_read(lt9611->regmap, 0x820c, &irq_flag0);379380/* hpd changed low */381if (irq_flag3 & 0x80) {382dev_info(lt9611->dev, "hdmi cable disconnected\n");383384regmap_write(lt9611->regmap, 0x8207, 0xbf);385regmap_write(lt9611->regmap, 0x8207, 0x3f);386}387388/* hpd changed high */389if (irq_flag3 & 0x40) {390dev_info(lt9611->dev, "hdmi cable connected\n");391392regmap_write(lt9611->regmap, 0x8207, 0x7f);393regmap_write(lt9611->regmap, 0x8207, 0x3f);394}395396if (irq_flag3 & 0xc0 && lt9611->bridge.dev)397drm_kms_helper_hotplug_event(lt9611->bridge.dev);398399/* video input changed */400if (irq_flag0 & 0x01) {401dev_info(lt9611->dev, "video input changed\n");402regmap_write(lt9611->regmap, 0x829e, 0xff);403regmap_write(lt9611->regmap, 0x829e, 0xf7);404regmap_write(lt9611->regmap, 0x8204, 0xff);405regmap_write(lt9611->regmap, 0x8204, 0xfe);406}407408return IRQ_HANDLED;409}410411static void lt9611_enable_hpd_interrupts(struct lt9611 *lt9611)412{413unsigned int val;414415regmap_read(lt9611->regmap, 0x8203, &val);416417val &= ~0xc0;418regmap_write(lt9611->regmap, 0x8203, val);419regmap_write(lt9611->regmap, 0x8207, 0xff); /* clear */420regmap_write(lt9611->regmap, 0x8207, 0x3f);421}422423static void lt9611_sleep_setup(struct lt9611 *lt9611)424{425const struct reg_sequence sleep_setup[] = {426{ 0x8024, 0x76 },427{ 0x8023, 0x01 },428{ 0x8157, 0x03 }, /* set addr pin as output */429{ 0x8149, 0x0b },430431{ 0x8102, 0x48 }, /* MIPI Rx power down */432{ 0x8123, 0x80 },433{ 0x8130, 0x00 },434{ 0x8011, 0x0a },435};436437regmap_multi_reg_write(lt9611->regmap,438sleep_setup, ARRAY_SIZE(sleep_setup));439lt9611->sleep = true;440}441442static int lt9611_power_on(struct lt9611 *lt9611)443{444int ret;445const struct reg_sequence seq[] = {446/* LT9611_System_Init */447{ 0x8101, 0x18 }, /* sel xtal clock */448449/* timer for frequency meter */450{ 0x821b, 0x69 }, /* timer 2 */451{ 0x821c, 0x78 },452{ 0x82cb, 0x69 }, /* timer 1 */453{ 0x82cc, 0x78 },454455/* irq init */456{ 0x8251, 0x01 },457{ 0x8258, 0x0a }, /* hpd irq */458{ 0x8259, 0x80 }, /* hpd debounce width */459{ 0x829e, 0xf7 }, /* video check irq */460461/* power consumption for work */462{ 0x8004, 0xf0 },463{ 0x8006, 0xf0 },464{ 0x800a, 0x80 },465{ 0x800b, 0x40 },466{ 0x800d, 0xef },467{ 0x8011, 0xfa },468};469470if (lt9611->power_on)471return 0;472473ret = regmap_multi_reg_write(lt9611->regmap, seq, ARRAY_SIZE(seq));474if (!ret)475lt9611->power_on = true;476477return ret;478}479480static int lt9611_power_off(struct lt9611 *lt9611)481{482int ret;483484ret = regmap_write(lt9611->regmap, 0x8130, 0x6a);485if (!ret)486lt9611->power_on = false;487488return ret;489}490491static void lt9611_reset(struct lt9611 *lt9611)492{493gpiod_set_value_cansleep(lt9611->reset_gpio, 1);494msleep(20);495496gpiod_set_value_cansleep(lt9611->reset_gpio, 0);497msleep(20);498499gpiod_set_value_cansleep(lt9611->reset_gpio, 1);500msleep(100);501}502503static void lt9611_assert_5v(struct lt9611 *lt9611)504{505if (!lt9611->enable_gpio)506return;507508gpiod_set_value_cansleep(lt9611->enable_gpio, 1);509msleep(20);510}511512static int lt9611_regulator_init(struct lt9611 *lt9611)513{514int ret;515516lt9611->supplies[0].supply = "vdd";517lt9611->supplies[1].supply = "vcc";518519ret = devm_regulator_bulk_get(lt9611->dev, 2, lt9611->supplies);520if (ret < 0)521return ret;522523return regulator_set_load(lt9611->supplies[0].consumer, 300000);524}525526static int lt9611_regulator_enable(struct lt9611 *lt9611)527{528int ret;529530ret = regulator_enable(lt9611->supplies[0].consumer);531if (ret < 0)532return ret;533534usleep_range(1000, 10000);535536ret = regulator_enable(lt9611->supplies[1].consumer);537if (ret < 0) {538regulator_disable(lt9611->supplies[0].consumer);539return ret;540}541542return 0;543}544545static enum drm_connector_status546lt9611_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector)547{548struct lt9611 *lt9611 = bridge_to_lt9611(bridge);549unsigned int reg_val = 0;550int connected = 0;551552regmap_read(lt9611->regmap, 0x825e, ®_val);553connected = (reg_val & (BIT(2) | BIT(0)));554555lt9611->status = connected ? connector_status_connected :556connector_status_disconnected;557558return lt9611->status;559}560561static int lt9611_read_edid(struct lt9611 *lt9611)562{563unsigned int temp;564int ret = 0;565int i, j;566567/* memset to clear old buffer, if any */568memset(lt9611->edid_buf, 0, sizeof(lt9611->edid_buf));569570regmap_write(lt9611->regmap, 0x8503, 0xc9);571572/* 0xA0 is EDID device address */573regmap_write(lt9611->regmap, 0x8504, 0xa0);574/* 0x00 is EDID offset address */575regmap_write(lt9611->regmap, 0x8505, 0x00);576577/* length for read */578regmap_write(lt9611->regmap, 0x8506, EDID_LEN);579regmap_write(lt9611->regmap, 0x8514, 0x7f);580581for (i = 0; i < EDID_LOOP; i++) {582/* offset address */583regmap_write(lt9611->regmap, 0x8505, i * EDID_LEN);584regmap_write(lt9611->regmap, 0x8507, 0x36);585regmap_write(lt9611->regmap, 0x8507, 0x31);586regmap_write(lt9611->regmap, 0x8507, 0x37);587usleep_range(5000, 10000);588589regmap_read(lt9611->regmap, 0x8540, &temp);590591if (temp & KEY_DDC_ACCS_DONE) {592for (j = 0; j < EDID_LEN; j++) {593regmap_read(lt9611->regmap, 0x8583, &temp);594lt9611->edid_buf[i * EDID_LEN + j] = temp;595}596597} else if (temp & DDC_NO_ACK) { /* DDC No Ack or Abitration lost */598dev_err(lt9611->dev, "read edid failed: no ack\n");599ret = -EIO;600goto end;601602} else {603dev_err(lt9611->dev, "read edid failed: access not done\n");604ret = -EIO;605goto end;606}607}608609end:610regmap_write(lt9611->regmap, 0x8507, 0x1f);611return ret;612}613614static int615lt9611_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)616{617struct lt9611 *lt9611 = data;618int ret;619620if (len > 128)621return -EINVAL;622623/* supports up to 1 extension block */624/* TODO: add support for more extension blocks */625if (block > 1)626return -EINVAL;627628if (block == 0) {629ret = lt9611_read_edid(lt9611);630if (ret) {631dev_err(lt9611->dev, "edid read failed\n");632return ret;633}634}635636block %= 2;637memcpy(buf, lt9611->edid_buf + (block * 128), len);638639return 0;640}641642/* bridge funcs */643static void lt9611_bridge_atomic_enable(struct drm_bridge *bridge,644struct drm_atomic_state *state)645{646struct lt9611 *lt9611 = bridge_to_lt9611(bridge);647struct drm_connector *connector;648struct drm_connector_state *conn_state;649struct drm_crtc_state *crtc_state;650struct drm_display_mode *mode;651unsigned int postdiv;652653connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);654if (WARN_ON(!connector))655return;656657conn_state = drm_atomic_get_new_connector_state(state, connector);658if (WARN_ON(!conn_state))659return;660661crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);662if (WARN_ON(!crtc_state))663return;664665mode = &crtc_state->adjusted_mode;666667lt9611_mipi_input_digital(lt9611, mode);668lt9611_pll_setup(lt9611, mode, &postdiv);669lt9611_mipi_video_setup(lt9611, mode);670lt9611_pcr_setup(lt9611, mode, postdiv);671672if (lt9611_power_on(lt9611)) {673dev_err(lt9611->dev, "power on failed\n");674return;675}676677lt9611_mipi_input_analog(lt9611);678drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);679lt9611_hdmi_tx_digital(lt9611, connector->display_info.is_hdmi);680lt9611_hdmi_tx_phy(lt9611);681682msleep(500);683684lt9611_video_check(lt9611);685686/* Enable HDMI output */687regmap_write(lt9611->regmap, 0x8130, 0xea);688}689690static void lt9611_bridge_atomic_disable(struct drm_bridge *bridge,691struct drm_atomic_state *state)692{693struct lt9611 *lt9611 = bridge_to_lt9611(bridge);694int ret;695696/* Disable HDMI output */697ret = regmap_write(lt9611->regmap, 0x8130, 0x6a);698if (ret) {699dev_err(lt9611->dev, "video on failed\n");700return;701}702703if (lt9611_power_off(lt9611)) {704dev_err(lt9611->dev, "power on failed\n");705return;706}707}708709static struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611,710struct device_node *dsi_node)711{712const struct mipi_dsi_device_info info = { "lt9611", 0, lt9611->dev->of_node};713struct mipi_dsi_device *dsi;714struct mipi_dsi_host *host;715struct device *dev = lt9611->dev;716int ret;717718host = of_find_mipi_dsi_host_by_node(dsi_node);719if (!host)720return ERR_PTR(dev_err_probe(lt9611->dev, -EPROBE_DEFER, "failed to find dsi host\n"));721722dsi = devm_mipi_dsi_device_register_full(dev, host, &info);723if (IS_ERR(dsi)) {724dev_err(lt9611->dev, "failed to create dsi device\n");725return dsi;726}727728dsi->lanes = 4;729dsi->format = MIPI_DSI_FMT_RGB888;730dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |731MIPI_DSI_MODE_VIDEO_HSE;732733ret = devm_mipi_dsi_attach(dev, dsi);734if (ret < 0) {735dev_err(dev, "failed to attach dsi to host\n");736return ERR_PTR(ret);737}738739return dsi;740}741742static int lt9611_bridge_attach(struct drm_bridge *bridge,743struct drm_encoder *encoder,744enum drm_bridge_attach_flags flags)745{746struct lt9611 *lt9611 = bridge_to_lt9611(bridge);747748return drm_bridge_attach(encoder, lt9611->next_bridge,749bridge, flags);750}751752static enum drm_mode_status lt9611_bridge_mode_valid(struct drm_bridge *bridge,753const struct drm_display_info *info,754const struct drm_display_mode *mode)755{756struct lt9611 *lt9611 = bridge_to_lt9611(bridge);757758if (mode->hdisplay > 3840)759return MODE_BAD_HVALUE;760761if (mode->hdisplay > 2000 && !lt9611->dsi1_node)762return MODE_PANEL;763764return MODE_OK;765}766767static void lt9611_bridge_atomic_pre_enable(struct drm_bridge *bridge,768struct drm_atomic_state *state)769{770struct lt9611 *lt9611 = bridge_to_lt9611(bridge);771static const struct reg_sequence reg_cfg[] = {772{ 0x8102, 0x12 },773{ 0x8123, 0x40 },774{ 0x8130, 0xea },775{ 0x8011, 0xfa },776};777778if (!lt9611->sleep)779return;780781regmap_multi_reg_write(lt9611->regmap,782reg_cfg, ARRAY_SIZE(reg_cfg));783784lt9611->sleep = false;785}786787static void lt9611_bridge_atomic_post_disable(struct drm_bridge *bridge,788struct drm_atomic_state *state)789{790struct lt9611 *lt9611 = bridge_to_lt9611(bridge);791792lt9611_sleep_setup(lt9611);793}794795static const struct drm_edid *lt9611_bridge_edid_read(struct drm_bridge *bridge,796struct drm_connector *connector)797{798struct lt9611 *lt9611 = bridge_to_lt9611(bridge);799800lt9611_power_on(lt9611);801return drm_edid_read_custom(connector, lt9611_get_edid_block, lt9611);802}803804static void lt9611_bridge_hpd_enable(struct drm_bridge *bridge)805{806struct lt9611 *lt9611 = bridge_to_lt9611(bridge);807808lt9611_enable_hpd_interrupts(lt9611);809}810811#define MAX_INPUT_SEL_FORMATS 1812813static u32 *814lt9611_atomic_get_input_bus_fmts(struct drm_bridge *bridge,815struct drm_bridge_state *bridge_state,816struct drm_crtc_state *crtc_state,817struct drm_connector_state *conn_state,818u32 output_fmt,819unsigned int *num_input_fmts)820{821u32 *input_fmts;822823*num_input_fmts = 0;824825input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),826GFP_KERNEL);827if (!input_fmts)828return NULL;829830/* This is the DSI-end bus format */831input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;832*num_input_fmts = 1;833834return input_fmts;835}836837/*838* Other working frames:839* - 0x01, 0x84df840* - 0x04, 0x84c0841*/842#define LT9611_INFOFRAME_AUDIO 0x02843#define LT9611_INFOFRAME_AVI 0x08844#define LT9611_INFOFRAME_SPD 0x10845#define LT9611_INFOFRAME_HDMI 0x20846847static int lt9611_hdmi_clear_audio_infoframe(struct drm_bridge *bridge)848{849struct lt9611 *lt9611 = bridge_to_lt9611(bridge);850851regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_AUDIO, 0);852853return 0;854}855856static int lt9611_hdmi_clear_avi_infoframe(struct drm_bridge *bridge)857{858struct lt9611 *lt9611 = bridge_to_lt9611(bridge);859860regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_AVI, 0);861862return 0;863}864865static int lt9611_hdmi_clear_spd_infoframe(struct drm_bridge *bridge)866{867struct lt9611 *lt9611 = bridge_to_lt9611(bridge);868869regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_SPD, 0);870871return 0;872}873874static int lt9611_hdmi_clear_hdmi_infoframe(struct drm_bridge *bridge)875{876struct lt9611 *lt9611 = bridge_to_lt9611(bridge);877878regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_HDMI, 0);879880return 0;881}882883static int lt9611_hdmi_write_audio_infoframe(struct drm_bridge *bridge,884const u8 *buffer, size_t len)885{886struct lt9611 *lt9611 = bridge_to_lt9611(bridge);887int i;888889for (i = 0; i < len; i++)890regmap_write(lt9611->regmap, 0x84b2 + i, buffer[i]);891892regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_AUDIO, LT9611_INFOFRAME_AUDIO);893894return 0;895}896897static int lt9611_hdmi_write_avi_infoframe(struct drm_bridge *bridge,898const u8 *buffer, size_t len)899{900struct lt9611 *lt9611 = bridge_to_lt9611(bridge);901int i;902903for (i = 0; i < len; i++)904regmap_write(lt9611->regmap, 0x8440 + i, buffer[i]);905906regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_AVI, LT9611_INFOFRAME_AVI);907908return 0;909}910911static int lt9611_hdmi_write_spd_infoframe(struct drm_bridge *bridge,912const u8 *buffer, size_t len)913{914struct lt9611 *lt9611 = bridge_to_lt9611(bridge);915int i;916917for (i = 0; i < len; i++)918regmap_write(lt9611->regmap, 0x8493 + i, buffer[i]);919920regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_SPD, LT9611_INFOFRAME_SPD);921922return 0;923}924925static int lt9611_hdmi_write_hdmi_infoframe(struct drm_bridge *bridge,926const u8 *buffer, size_t len)927{928struct lt9611 *lt9611 = bridge_to_lt9611(bridge);929int i;930931for (i = 0; i < len; i++)932regmap_write(lt9611->regmap, 0x8474 + i, buffer[i]);933934regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_HDMI, LT9611_INFOFRAME_HDMI);935936return 0;937}938939static enum drm_mode_status940lt9611_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,941const struct drm_display_mode *mode,942unsigned long long tmds_rate)943{944/* 297 MHz for 4k@30 mode */945if (tmds_rate > 297000000)946return MODE_CLOCK_HIGH;947948return MODE_OK;949}950951static int lt9611_hdmi_audio_startup(struct drm_bridge *bridge,952struct drm_connector *connector)953{954struct lt9611 *lt9611 = bridge_to_lt9611(bridge);955956regmap_write(lt9611->regmap, 0x82d6, 0x8c);957regmap_write(lt9611->regmap, 0x82d7, 0x04);958959regmap_write(lt9611->regmap, 0x8406, 0x08);960regmap_write(lt9611->regmap, 0x8407, 0x10);961962regmap_write(lt9611->regmap, 0x8434, 0xd5);963964return 0;965}966967static int lt9611_hdmi_audio_prepare(struct drm_bridge *bridge,968struct drm_connector *connector,969struct hdmi_codec_daifmt *fmt,970struct hdmi_codec_params *hparms)971{972struct lt9611 *lt9611 = bridge_to_lt9611(bridge);973974if (hparms->sample_rate == 48000)975regmap_write(lt9611->regmap, 0x840f, 0x2b);976else if (hparms->sample_rate == 96000)977regmap_write(lt9611->regmap, 0x840f, 0xab);978else979return -EINVAL;980981regmap_write(lt9611->regmap, 0x8435, 0x00);982regmap_write(lt9611->regmap, 0x8436, 0x18);983regmap_write(lt9611->regmap, 0x8437, 0x00);984985return drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector,986&hparms->cea);987}988989static void lt9611_hdmi_audio_shutdown(struct drm_bridge *bridge,990struct drm_connector *connector)991{992struct lt9611 *lt9611 = bridge_to_lt9611(bridge);993994drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector);995996regmap_write(lt9611->regmap, 0x8406, 0x00);997regmap_write(lt9611->regmap, 0x8407, 0x00);998}9991000static const struct drm_bridge_funcs lt9611_bridge_funcs = {1001.attach = lt9611_bridge_attach,1002.mode_valid = lt9611_bridge_mode_valid,1003.detect = lt9611_bridge_detect,1004.edid_read = lt9611_bridge_edid_read,1005.hpd_enable = lt9611_bridge_hpd_enable,10061007.atomic_pre_enable = lt9611_bridge_atomic_pre_enable,1008.atomic_enable = lt9611_bridge_atomic_enable,1009.atomic_disable = lt9611_bridge_atomic_disable,1010.atomic_post_disable = lt9611_bridge_atomic_post_disable,1011.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,1012.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,1013.atomic_reset = drm_atomic_helper_bridge_reset,1014.atomic_get_input_bus_fmts = lt9611_atomic_get_input_bus_fmts,10151016.hdmi_tmds_char_rate_valid = lt9611_hdmi_tmds_char_rate_valid,1017.hdmi_write_audio_infoframe = lt9611_hdmi_write_audio_infoframe,1018.hdmi_clear_audio_infoframe = lt9611_hdmi_clear_audio_infoframe,1019.hdmi_write_avi_infoframe = lt9611_hdmi_write_avi_infoframe,1020.hdmi_clear_avi_infoframe = lt9611_hdmi_clear_avi_infoframe,1021.hdmi_write_spd_infoframe = lt9611_hdmi_write_spd_infoframe,1022.hdmi_clear_spd_infoframe = lt9611_hdmi_clear_spd_infoframe,1023.hdmi_write_hdmi_infoframe = lt9611_hdmi_write_hdmi_infoframe,1024.hdmi_clear_hdmi_infoframe = lt9611_hdmi_clear_hdmi_infoframe,10251026.hdmi_audio_startup = lt9611_hdmi_audio_startup,1027.hdmi_audio_prepare = lt9611_hdmi_audio_prepare,1028.hdmi_audio_shutdown = lt9611_hdmi_audio_shutdown,1029};10301031static int lt9611_parse_dt(struct device *dev,1032struct lt9611 *lt9611)1033{1034lt9611->dsi0_node = of_graph_get_remote_node(dev->of_node, 0, -1);1035if (!lt9611->dsi0_node) {1036dev_err(lt9611->dev, "failed to get remote node for primary dsi\n");1037return -ENODEV;1038}10391040lt9611->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1);10411042lt9611->ac_mode = of_property_read_bool(dev->of_node, "lt,ac-mode");10431044return drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, <9611->next_bridge);1045}10461047static int lt9611_gpio_init(struct lt9611 *lt9611)1048{1049struct device *dev = lt9611->dev;10501051lt9611->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);1052if (IS_ERR(lt9611->reset_gpio)) {1053dev_err(dev, "failed to acquire reset gpio\n");1054return PTR_ERR(lt9611->reset_gpio);1055}10561057lt9611->enable_gpio = devm_gpiod_get_optional(dev, "enable",1058GPIOD_OUT_LOW);1059if (IS_ERR(lt9611->enable_gpio)) {1060dev_err(dev, "failed to acquire enable gpio\n");1061return PTR_ERR(lt9611->enable_gpio);1062}10631064return 0;1065}10661067static int lt9611_read_device_rev(struct lt9611 *lt9611)1068{1069unsigned int rev;1070int ret;10711072regmap_write(lt9611->regmap, 0x80ee, 0x01);1073ret = regmap_read(lt9611->regmap, 0x8002, &rev);1074if (ret)1075dev_err(lt9611->dev, "failed to read revision: %d\n", ret);1076else1077dev_info(lt9611->dev, "LT9611 revision: 0x%x\n", rev);10781079return ret;1080}10811082static int lt9611_probe(struct i2c_client *client)1083{1084struct lt9611 *lt9611;1085struct device *dev = &client->dev;1086int ret;10871088if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {1089dev_err(dev, "device doesn't support I2C\n");1090return -ENODEV;1091}10921093lt9611 = devm_drm_bridge_alloc(dev, struct lt9611, bridge,1094<9611_bridge_funcs);1095if (IS_ERR(lt9611))1096return PTR_ERR(lt9611);10971098lt9611->dev = dev;1099lt9611->client = client;1100lt9611->sleep = false;11011102lt9611->regmap = devm_regmap_init_i2c(client, <9611_regmap_config);1103if (IS_ERR(lt9611->regmap)) {1104dev_err(lt9611->dev, "regmap i2c init failed\n");1105return PTR_ERR(lt9611->regmap);1106}11071108ret = lt9611_parse_dt(dev, lt9611);1109if (ret) {1110dev_err(dev, "failed to parse device tree\n");1111return ret;1112}11131114ret = lt9611_gpio_init(lt9611);1115if (ret < 0)1116goto err_of_put;11171118ret = lt9611_regulator_init(lt9611);1119if (ret < 0)1120goto err_of_put;11211122lt9611_assert_5v(lt9611);11231124ret = lt9611_regulator_enable(lt9611);1125if (ret)1126goto err_of_put;11271128lt9611_reset(lt9611);11291130ret = lt9611_read_device_rev(lt9611);1131if (ret) {1132dev_err(dev, "failed to read chip rev\n");1133goto err_disable_regulators;1134}11351136ret = devm_request_threaded_irq(dev, client->irq, NULL,1137lt9611_irq_thread_handler,1138IRQF_ONESHOT, "lt9611", lt9611);1139if (ret) {1140dev_err(dev, "failed to request irq\n");1141goto err_disable_regulators;1142}11431144i2c_set_clientdata(client, lt9611);11451146/* Disable Audio InfoFrame, enabled by default */1147regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_AUDIO, 0);11481149lt9611->bridge.of_node = client->dev.of_node;1150lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |1151DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES |1152DRM_BRIDGE_OP_HDMI | DRM_BRIDGE_OP_HDMI_AUDIO |1153DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME;1154lt9611->bridge.type = DRM_MODE_CONNECTOR_HDMIA;1155lt9611->bridge.vendor = "Lontium";1156lt9611->bridge.product = "LT9611";1157lt9611->bridge.hdmi_audio_dev = dev;1158lt9611->bridge.hdmi_audio_max_i2s_playback_channels = 8;1159lt9611->bridge.hdmi_audio_dai_port = 2;11601161drm_bridge_add(<9611->bridge);11621163/* Attach primary DSI */1164lt9611->dsi0 = lt9611_attach_dsi(lt9611, lt9611->dsi0_node);1165if (IS_ERR(lt9611->dsi0)) {1166ret = PTR_ERR(lt9611->dsi0);1167goto err_remove_bridge;1168}11691170/* Attach secondary DSI, if specified */1171if (lt9611->dsi1_node) {1172lt9611->dsi1 = lt9611_attach_dsi(lt9611, lt9611->dsi1_node);1173if (IS_ERR(lt9611->dsi1)) {1174ret = PTR_ERR(lt9611->dsi1);1175goto err_remove_bridge;1176}1177}11781179lt9611_enable_hpd_interrupts(lt9611);11801181return 0;11821183err_remove_bridge:1184drm_bridge_remove(<9611->bridge);11851186err_disable_regulators:1187regulator_bulk_disable(ARRAY_SIZE(lt9611->supplies), lt9611->supplies);11881189err_of_put:1190of_node_put(lt9611->dsi1_node);1191of_node_put(lt9611->dsi0_node);11921193return ret;1194}11951196static void lt9611_remove(struct i2c_client *client)1197{1198struct lt9611 *lt9611 = i2c_get_clientdata(client);11991200disable_irq(client->irq);1201drm_bridge_remove(<9611->bridge);12021203regulator_bulk_disable(ARRAY_SIZE(lt9611->supplies), lt9611->supplies);12041205of_node_put(lt9611->dsi1_node);1206of_node_put(lt9611->dsi0_node);1207}12081209static const struct i2c_device_id lt9611_id[] = {1210{ "lontium,lt9611" },1211{}1212};1213MODULE_DEVICE_TABLE(i2c, lt9611_id);12141215static const struct of_device_id lt9611_match_table[] = {1216{ .compatible = "lontium,lt9611" },1217{ }1218};1219MODULE_DEVICE_TABLE(of, lt9611_match_table);12201221static struct i2c_driver lt9611_driver = {1222.driver = {1223.name = "lt9611",1224.of_match_table = lt9611_match_table,1225},1226.probe = lt9611_probe,1227.remove = lt9611_remove,1228.id_table = lt9611_id,1229};1230module_i2c_driver(lt9611_driver);12311232MODULE_DESCRIPTION("Lontium LT9611 DSI/HDMI bridge driver");1233MODULE_LICENSE("GPL v2");123412351236