Path: blob/master/drivers/gpu/drm/bridge/lontium-lt9211.c
51759 views
// SPDX-License-Identifier: GPL-2.01/*2* Lontium LT9211 bridge driver3*4* LT9211 is capable of converting:5* 2xDSI/2xLVDS/1xDPI -> 2xDSI/2xLVDS/1xDPI6* Currently supported is:7* 1xDSI -> 1xLVDS8*9* Copyright (C) 2022 Marek Vasut <[email protected]>10*/1112#include <linux/bits.h>13#include <linux/clk.h>14#include <linux/gpio/consumer.h>15#include <linux/i2c.h>16#include <linux/media-bus-format.h>17#include <linux/module.h>18#include <linux/of_graph.h>19#include <linux/regmap.h>20#include <linux/regulator/consumer.h>2122#include <drm/drm_atomic_helper.h>23#include <drm/drm_bridge.h>24#include <drm/drm_mipi_dsi.h>25#include <drm/drm_of.h>26#include <drm/drm_panel.h>27#include <drm/drm_print.h>28#include <drm/drm_probe_helper.h>2930#define REG_PAGE_CONTROL 0xff31#define REG_CHIPID0 0x810032#define REG_CHIPID0_VALUE 0x1833#define REG_CHIPID1 0x810134#define REG_CHIPID1_VALUE 0x0135#define REG_CHIPID2 0x810236#define REG_CHIPID2_VALUE 0xe33738#define REG_DSI_LANE 0xd00039/* DSI lane count - 0 means 4 lanes ; 1, 2, 3 means 1, 2, 3 lanes. */40#define REG_DSI_LANE_COUNT(n) ((n) & 3)4142struct lt9211 {43struct drm_bridge bridge;44struct device *dev;45struct regmap *regmap;46struct mipi_dsi_device *dsi;47struct drm_bridge *panel_bridge;48struct gpio_desc *reset_gpio;49struct regulator *vccio;50bool lvds_dual_link;51bool lvds_dual_link_even_odd_swap;52};5354static const struct regmap_range lt9211_rw_ranges[] = {55regmap_reg_range(0xff, 0xff),56regmap_reg_range(0x8100, 0x816b),57regmap_reg_range(0x8200, 0x82aa),58regmap_reg_range(0x8500, 0x85ff),59regmap_reg_range(0x8600, 0x86a0),60regmap_reg_range(0x8700, 0x8746),61regmap_reg_range(0xd000, 0xd0a7),62regmap_reg_range(0xd400, 0xd42c),63regmap_reg_range(0xd800, 0xd838),64regmap_reg_range(0xd9c0, 0xd9d5),65};6667static const struct regmap_access_table lt9211_rw_table = {68.yes_ranges = lt9211_rw_ranges,69.n_yes_ranges = ARRAY_SIZE(lt9211_rw_ranges),70};7172static const struct regmap_range_cfg lt9211_range = {73.name = "lt9211",74.range_min = 0x0000,75.range_max = 0xda00,76.selector_reg = REG_PAGE_CONTROL,77.selector_mask = 0xff,78.selector_shift = 0,79.window_start = 0,80.window_len = 0x100,81};8283static const struct regmap_config lt9211_regmap_config = {84.reg_bits = 8,85.val_bits = 8,86.rd_table = <9211_rw_table,87.wr_table = <9211_rw_table,88.volatile_table = <9211_rw_table,89.ranges = <9211_range,90.num_ranges = 1,91.cache_type = REGCACHE_MAPLE,92.max_register = 0xda00,93};9495static struct lt9211 *bridge_to_lt9211(struct drm_bridge *bridge)96{97return container_of(bridge, struct lt9211, bridge);98}99100static int lt9211_attach(struct drm_bridge *bridge,101struct drm_encoder *encoder,102enum drm_bridge_attach_flags flags)103{104struct lt9211 *ctx = bridge_to_lt9211(bridge);105106return drm_bridge_attach(encoder, ctx->panel_bridge,107&ctx->bridge, flags);108}109110static int lt9211_read_chipid(struct lt9211 *ctx)111{112u8 chipid[3];113int ret;114115/* Read Chip ID registers and verify the chip can communicate. */116ret = regmap_bulk_read(ctx->regmap, REG_CHIPID0, chipid, 3);117if (ret < 0) {118dev_err(ctx->dev, "Failed to read Chip ID: %d\n", ret);119return ret;120}121122/* Test for known Chip ID. */123if (chipid[0] != REG_CHIPID0_VALUE || chipid[1] != REG_CHIPID1_VALUE) {124dev_err(ctx->dev, "Unknown Chip ID: 0x%02x 0x%02x 0x%02x\n",125chipid[0], chipid[1], chipid[2]);126return -EINVAL;127}128129return 0;130}131132static int lt9211_system_init(struct lt9211 *ctx)133{134const struct reg_sequence lt9211_system_init_seq[] = {135{ 0x8201, 0x18 },136{ 0x8606, 0x61 },137{ 0x8607, 0xa8 },138{ 0x8714, 0x08 },139{ 0x8715, 0x00 },140{ 0x8718, 0x0f },141{ 0x8722, 0x08 },142{ 0x8723, 0x00 },143{ 0x8726, 0x0f },144{ 0x810b, 0xfe },145};146147return regmap_multi_reg_write(ctx->regmap, lt9211_system_init_seq,148ARRAY_SIZE(lt9211_system_init_seq));149}150151static int lt9211_configure_rx(struct lt9211 *ctx)152{153const struct reg_sequence lt9211_rx_phy_seq[] = {154{ 0x8202, 0x44 },155{ 0x8204, 0xa0 },156{ 0x8205, 0x22 },157{ 0x8207, 0x9f },158{ 0x8208, 0xfc },159/* ORR with 0xf8 here to enable DSI DN/DP swap. */160{ 0x8209, 0x01 },161{ 0x8217, 0x0c },162{ 0x8633, 0x1b },163};164165const struct reg_sequence lt9211_rx_cal_reset_seq[] = {166{ 0x8120, 0x7f },167{ 0x8120, 0xff },168};169170const struct reg_sequence lt9211_rx_dig_seq[] = {171{ 0x8630, 0x85 },172/* 0x8588: BIT 6 set = MIPI-RX, BIT 4 unset = LVDS-TX */173{ 0x8588, 0x40 },174{ 0x85ff, 0xd0 },175{ REG_DSI_LANE, REG_DSI_LANE_COUNT(ctx->dsi->lanes) },176{ 0xd002, 0x05 },177};178179const struct reg_sequence lt9211_rx_div_reset_seq[] = {180{ 0x810a, 0xc0 },181{ 0x8120, 0xbf },182};183184const struct reg_sequence lt9211_rx_div_clear_seq[] = {185{ 0x810a, 0xc1 },186{ 0x8120, 0xff },187};188189int ret;190191ret = regmap_multi_reg_write(ctx->regmap, lt9211_rx_phy_seq,192ARRAY_SIZE(lt9211_rx_phy_seq));193if (ret)194return ret;195196ret = regmap_multi_reg_write(ctx->regmap, lt9211_rx_cal_reset_seq,197ARRAY_SIZE(lt9211_rx_cal_reset_seq));198if (ret)199return ret;200201ret = regmap_multi_reg_write(ctx->regmap, lt9211_rx_dig_seq,202ARRAY_SIZE(lt9211_rx_dig_seq));203if (ret)204return ret;205206ret = regmap_multi_reg_write(ctx->regmap, lt9211_rx_div_reset_seq,207ARRAY_SIZE(lt9211_rx_div_reset_seq));208if (ret)209return ret;210211usleep_range(10000, 15000);212213return regmap_multi_reg_write(ctx->regmap, lt9211_rx_div_clear_seq,214ARRAY_SIZE(lt9211_rx_div_clear_seq));215}216217static int lt9211_autodetect_rx(struct lt9211 *ctx,218const struct drm_display_mode *mode)219{220u16 width, height;221u32 byteclk;222u8 buf[5];223u8 format;224u8 bc[3];225int ret;226227/* Measure ByteClock frequency. */228ret = regmap_write(ctx->regmap, 0x8600, 0x01);229if (ret)230return ret;231232/* Give the chip time to lock onto RX stream. */233msleep(100);234235/* Read the ByteClock frequency from the chip. */236ret = regmap_bulk_read(ctx->regmap, 0x8608, bc, sizeof(bc));237if (ret)238return ret;239240/* RX ByteClock in kHz */241byteclk = ((bc[0] & 0xf) << 16) | (bc[1] << 8) | bc[2];242243/* Width/Height/Format Auto-detection */244ret = regmap_bulk_read(ctx->regmap, 0xd082, buf, sizeof(buf));245if (ret)246return ret;247248width = (buf[0] << 8) | buf[1];249height = (buf[3] << 8) | buf[4];250format = buf[2] & 0xf;251252if (format == 0x3) { /* YUV422 16bit */253width /= 2;254} else if (format == 0xa) { /* RGB888 24bit */255width /= 3;256} else {257dev_err(ctx->dev, "Unsupported DSI pixel format 0x%01x\n",258format);259return -EINVAL;260}261262if (width != mode->hdisplay) {263dev_err(ctx->dev,264"RX: Detected DSI width (%d) does not match mode hdisplay (%d)\n",265width, mode->hdisplay);266return -EINVAL;267}268269if (height != mode->vdisplay) {270dev_err(ctx->dev,271"RX: Detected DSI height (%d) does not match mode vdisplay (%d)\n",272height, mode->vdisplay);273return -EINVAL;274}275276dev_dbg(ctx->dev, "RX: %dx%d format=0x%01x byteclock=%d kHz\n",277width, height, format, byteclk);278279return 0;280}281282static int lt9211_configure_timing(struct lt9211 *ctx,283const struct drm_display_mode *mode)284{285const struct reg_sequence lt9211_timing[] = {286{ 0xd00d, (mode->vtotal >> 8) & 0xff },287{ 0xd00e, mode->vtotal & 0xff },288{ 0xd00f, (mode->vdisplay >> 8) & 0xff },289{ 0xd010, mode->vdisplay & 0xff },290{ 0xd011, (mode->htotal >> 8) & 0xff },291{ 0xd012, mode->htotal & 0xff },292{ 0xd013, (mode->hdisplay >> 8) & 0xff },293{ 0xd014, mode->hdisplay & 0xff },294{ 0xd015, (mode->vsync_end - mode->vsync_start) & 0xff },295{ 0xd016, (mode->hsync_end - mode->hsync_start) & 0xff },296{ 0xd017, ((mode->vsync_start - mode->vdisplay) >> 8) & 0xff },297{ 0xd018, (mode->vsync_start - mode->vdisplay) & 0xff },298{ 0xd019, ((mode->hsync_start - mode->hdisplay) >> 8) & 0xff },299{ 0xd01a, (mode->hsync_start - mode->hdisplay) & 0xff },300};301302return regmap_multi_reg_write(ctx->regmap, lt9211_timing,303ARRAY_SIZE(lt9211_timing));304}305306static int lt9211_configure_plls(struct lt9211 *ctx,307const struct drm_display_mode *mode)308{309const struct reg_sequence lt9211_pcr_seq[] = {310{ 0xd026, 0x17 },311{ 0xd027, 0xc3 },312{ 0xd02d, 0x30 },313{ 0xd031, 0x10 },314{ 0xd023, 0x20 },315{ 0xd038, 0x02 },316{ 0xd039, 0x10 },317{ 0xd03a, 0x20 },318{ 0xd03b, 0x60 },319{ 0xd03f, 0x04 },320{ 0xd040, 0x08 },321{ 0xd041, 0x10 },322{ 0x810b, 0xee },323{ 0x810b, 0xfe },324};325326unsigned int pval;327int ret;328329/* DeSSC PLL reference clock is 25 MHz XTal. */330ret = regmap_write(ctx->regmap, 0x822d, 0x48);331if (ret)332return ret;333334if (mode->clock < 44000) {335ret = regmap_write(ctx->regmap, 0x8235, 0x83);336} else if (mode->clock < 88000) {337ret = regmap_write(ctx->regmap, 0x8235, 0x82);338} else if (mode->clock < 176000) {339ret = regmap_write(ctx->regmap, 0x8235, 0x81);340} else {341dev_err(ctx->dev,342"Unsupported mode clock (%d kHz) above 176 MHz.\n",343mode->clock);344return -EINVAL;345}346347if (ret)348return ret;349350/* Wait for the DeSSC PLL to stabilize. */351msleep(100);352353ret = regmap_multi_reg_write(ctx->regmap, lt9211_pcr_seq,354ARRAY_SIZE(lt9211_pcr_seq));355if (ret)356return ret;357358/* PCR stability test takes seconds. */359ret = regmap_read_poll_timeout(ctx->regmap, 0xd087, pval, pval & 0x8,36020000, 10000000);361if (ret)362dev_err(ctx->dev, "PCR unstable, ret=%i\n", ret);363364return ret;365}366367static int lt9211_configure_tx(struct lt9211 *ctx, bool jeida,368bool bpp24, bool de)369{370const struct reg_sequence system_lt9211_tx_phy_seq[] = {371/* DPI output disable */372{ 0x8262, 0x00 },373/* BIT(7) is LVDS dual-port */374{ 0x823b, 0x38 | (ctx->lvds_dual_link ? BIT(7) : 0) },375{ 0x823e, 0x92 },376{ 0x823f, 0x48 },377{ 0x8240, 0x31 },378{ 0x8243, 0x80 },379{ 0x8244, 0x00 },380{ 0x8245, 0x00 },381{ 0x8249, 0x00 },382{ 0x824a, 0x01 },383{ 0x824e, 0x00 },384{ 0x824f, 0x00 },385{ 0x8250, 0x00 },386{ 0x8253, 0x00 },387{ 0x8254, 0x01 },388/* LVDS channel order, Odd:Even 0x10..A:B, 0x40..B:A */389{ 0x8646, ctx->lvds_dual_link_even_odd_swap ? 0x40 : 0x10 },390{ 0x8120, 0x7b },391{ 0x816b, 0xff },392};393394const struct reg_sequence system_lt9211_tx_dig_seq[] = {395{ 0x8559, 0x40 | (jeida ? BIT(7) : 0) |396(de ? BIT(5) : 0) | (bpp24 ? BIT(4) : 0) },397{ 0x855a, 0xaa },398{ 0x855b, 0xaa },399{ 0x855c, ctx->lvds_dual_link ? BIT(0) : 0 },400{ 0x85a1, 0x77 },401{ 0x8640, 0x40 },402{ 0x8641, 0x34 },403{ 0x8642, 0x10 },404{ 0x8643, 0x23 },405{ 0x8644, 0x41 },406{ 0x8645, 0x02 },407};408409const struct reg_sequence system_lt9211_tx_pll_seq[] = {410/* TX PLL power down */411{ 0x8236, 0x01 },412{ 0x8237, ctx->lvds_dual_link ? 0x2a : 0x29 },413{ 0x8238, 0x06 },414{ 0x8239, 0x30 },415{ 0x823a, 0x8e },416{ 0x8737, 0x14 },417{ 0x8713, 0x00 },418{ 0x8713, 0x80 },419};420421unsigned int pval;422int ret;423424ret = regmap_multi_reg_write(ctx->regmap, system_lt9211_tx_phy_seq,425ARRAY_SIZE(system_lt9211_tx_phy_seq));426if (ret)427return ret;428429ret = regmap_multi_reg_write(ctx->regmap, system_lt9211_tx_dig_seq,430ARRAY_SIZE(system_lt9211_tx_dig_seq));431if (ret)432return ret;433434ret = regmap_multi_reg_write(ctx->regmap, system_lt9211_tx_pll_seq,435ARRAY_SIZE(system_lt9211_tx_pll_seq));436if (ret)437return ret;438439ret = regmap_read_poll_timeout(ctx->regmap, 0x871f, pval, pval & 0x80,44010000, 1000000);441if (ret) {442dev_err(ctx->dev, "TX PLL unstable, ret=%i\n", ret);443return ret;444}445446ret = regmap_read_poll_timeout(ctx->regmap, 0x8720, pval, pval & 0x80,44710000, 1000000);448if (ret) {449dev_err(ctx->dev, "TX PLL unstable, ret=%i\n", ret);450return ret;451}452453return 0;454}455456static void lt9211_atomic_enable(struct drm_bridge *bridge,457struct drm_atomic_state *state)458{459struct lt9211 *ctx = bridge_to_lt9211(bridge);460const struct drm_bridge_state *bridge_state;461const struct drm_crtc_state *crtc_state;462const struct drm_display_mode *mode;463struct drm_connector *connector;464struct drm_crtc *crtc;465bool lvds_format_24bpp;466bool lvds_format_jeida;467u32 bus_flags;468int ret;469470ret = regulator_enable(ctx->vccio);471if (ret) {472dev_err(ctx->dev, "Failed to enable vccio: %d\n", ret);473return;474}475476/* Deassert reset */477gpiod_set_value(ctx->reset_gpio, 1);478usleep_range(20000, 21000); /* Very long post-reset delay. */479480/* Get the LVDS format from the bridge state. */481bridge_state = drm_atomic_get_new_bridge_state(state, bridge);482bus_flags = bridge_state->output_bus_cfg.flags;483484switch (bridge_state->output_bus_cfg.format) {485case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:486lvds_format_24bpp = false;487lvds_format_jeida = true;488break;489case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:490lvds_format_24bpp = true;491lvds_format_jeida = true;492break;493case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:494lvds_format_24bpp = true;495lvds_format_jeida = false;496break;497default:498/*499* Some bridges still don't set the correct500* LVDS bus pixel format, use SPWG24 default501* format until those are fixed.502*/503lvds_format_24bpp = true;504lvds_format_jeida = false;505dev_warn(ctx->dev,506"Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n",507bridge_state->output_bus_cfg.format);508break;509}510511/*512* Retrieve the CRTC adjusted mode. This requires a little dance to go513* from the bridge to the encoder, to the connector and to the CRTC.514*/515connector = drm_atomic_get_new_connector_for_encoder(state,516bridge->encoder);517crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;518crtc_state = drm_atomic_get_new_crtc_state(state, crtc);519mode = &crtc_state->adjusted_mode;520521ret = lt9211_read_chipid(ctx);522if (ret)523return;524525ret = lt9211_system_init(ctx);526if (ret)527return;528529ret = lt9211_configure_rx(ctx);530if (ret)531return;532533ret = lt9211_autodetect_rx(ctx, mode);534if (ret)535return;536537ret = lt9211_configure_timing(ctx, mode);538if (ret)539return;540541ret = lt9211_configure_plls(ctx, mode);542if (ret)543return;544545ret = lt9211_configure_tx(ctx, lvds_format_jeida, lvds_format_24bpp,546bus_flags & DRM_BUS_FLAG_DE_HIGH);547if (ret)548return;549550dev_dbg(ctx->dev, "LT9211 enabled.\n");551}552553static void lt9211_atomic_disable(struct drm_bridge *bridge,554struct drm_atomic_state *state)555{556struct lt9211 *ctx = bridge_to_lt9211(bridge);557int ret;558559/*560* Put the chip in reset, pull nRST line low,561* and assure lengthy 10ms reset low timing.562*/563gpiod_set_value(ctx->reset_gpio, 0);564usleep_range(10000, 11000); /* Very long reset duration. */565566ret = regulator_disable(ctx->vccio);567if (ret)568dev_err(ctx->dev, "Failed to disable vccio: %d\n", ret);569570regcache_mark_dirty(ctx->regmap);571}572573static enum drm_mode_status574lt9211_mode_valid(struct drm_bridge *bridge,575const struct drm_display_info *info,576const struct drm_display_mode *mode)577{578/* LVDS output clock range 25..176 MHz */579if (mode->clock < 25000)580return MODE_CLOCK_LOW;581if (mode->clock > 176000)582return MODE_CLOCK_HIGH;583584return MODE_OK;585}586587#define MAX_INPUT_SEL_FORMATS 1588589static u32 *590lt9211_atomic_get_input_bus_fmts(struct drm_bridge *bridge,591struct drm_bridge_state *bridge_state,592struct drm_crtc_state *crtc_state,593struct drm_connector_state *conn_state,594u32 output_fmt,595unsigned int *num_input_fmts)596{597u32 *input_fmts;598599*num_input_fmts = 0;600601input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),602GFP_KERNEL);603if (!input_fmts)604return NULL;605606/* This is the DSI-end bus format */607input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;608*num_input_fmts = 1;609610return input_fmts;611}612613static const struct drm_bridge_funcs lt9211_funcs = {614.attach = lt9211_attach,615.mode_valid = lt9211_mode_valid,616.atomic_enable = lt9211_atomic_enable,617.atomic_disable = lt9211_atomic_disable,618.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,619.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,620.atomic_get_input_bus_fmts = lt9211_atomic_get_input_bus_fmts,621.atomic_reset = drm_atomic_helper_bridge_reset,622};623624static int lt9211_parse_dt(struct lt9211 *ctx)625{626struct device_node *port2, *port3;627struct drm_bridge *panel_bridge;628struct device *dev = ctx->dev;629struct drm_panel *panel;630int dual_link;631int ret;632633ctx->vccio = devm_regulator_get(dev, "vccio");634if (IS_ERR(ctx->vccio))635return dev_err_probe(dev, PTR_ERR(ctx->vccio),636"Failed to get supply 'vccio'\n");637638ctx->lvds_dual_link = false;639ctx->lvds_dual_link_even_odd_swap = false;640641port2 = of_graph_get_port_by_id(dev->of_node, 2);642port3 = of_graph_get_port_by_id(dev->of_node, 3);643dual_link = drm_of_lvds_get_dual_link_pixel_order(port2, port3);644of_node_put(port2);645of_node_put(port3);646647if (dual_link == DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS) {648ctx->lvds_dual_link = true;649/* Odd pixels to LVDS Channel A, even pixels to B */650ctx->lvds_dual_link_even_odd_swap = false;651} else if (dual_link == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) {652ctx->lvds_dual_link = true;653/* Even pixels to LVDS Channel A, odd pixels to B */654ctx->lvds_dual_link_even_odd_swap = true;655}656657ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, &panel_bridge);658if (ret < 0)659return ret;660if (panel) {661panel_bridge = devm_drm_panel_bridge_add(dev, panel);662if (IS_ERR(panel_bridge))663return PTR_ERR(panel_bridge);664}665666ctx->panel_bridge = panel_bridge;667668return 0;669}670671static int lt9211_host_attach(struct lt9211 *ctx)672{673const struct mipi_dsi_device_info info = {674.type = "lt9211",675.channel = 0,676.node = NULL,677};678struct device *dev = ctx->dev;679struct device_node *host_node;680struct device_node *endpoint;681struct mipi_dsi_device *dsi;682struct mipi_dsi_host *host;683int dsi_lanes;684int ret;685686endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);687dsi_lanes = drm_of_get_data_lanes_count(endpoint, 1, 4);688host_node = of_graph_get_remote_port_parent(endpoint);689host = of_find_mipi_dsi_host_by_node(host_node);690of_node_put(host_node);691of_node_put(endpoint);692693if (!host)694return -EPROBE_DEFER;695696if (dsi_lanes < 0)697return dsi_lanes;698699dsi = devm_mipi_dsi_device_register_full(dev, host, &info);700if (IS_ERR(dsi))701return dev_err_probe(dev, PTR_ERR(dsi),702"failed to create dsi device\n");703704ctx->dsi = dsi;705706dsi->lanes = dsi_lanes;707dsi->format = MIPI_DSI_FMT_RGB888;708dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |709MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA |710MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP |711MIPI_DSI_MODE_NO_EOT_PACKET;712713ret = devm_mipi_dsi_attach(dev, dsi);714if (ret < 0) {715dev_err(dev, "failed to attach dsi to host: %d\n", ret);716return ret;717}718719return 0;720}721722static int lt9211_probe(struct i2c_client *client)723{724struct device *dev = &client->dev;725struct lt9211 *ctx;726int ret;727728ctx = devm_drm_bridge_alloc(dev, struct lt9211, bridge, <9211_funcs);729if (IS_ERR(ctx))730return PTR_ERR(ctx);731732ctx->dev = dev;733734/*735* Put the chip in reset, pull nRST line low,736* and assure lengthy 10ms reset low timing.737*/738ctx->reset_gpio = devm_gpiod_get_optional(ctx->dev, "reset",739GPIOD_OUT_LOW);740if (IS_ERR(ctx->reset_gpio))741return PTR_ERR(ctx->reset_gpio);742743usleep_range(10000, 11000); /* Very long reset duration. */744745ret = lt9211_parse_dt(ctx);746if (ret)747return ret;748749ctx->regmap = devm_regmap_init_i2c(client, <9211_regmap_config);750if (IS_ERR(ctx->regmap))751return PTR_ERR(ctx->regmap);752753dev_set_drvdata(dev, ctx);754i2c_set_clientdata(client, ctx);755756ctx->bridge.of_node = dev->of_node;757drm_bridge_add(&ctx->bridge);758759ret = lt9211_host_attach(ctx);760if (ret)761drm_bridge_remove(&ctx->bridge);762763return ret;764}765766static void lt9211_remove(struct i2c_client *client)767{768struct lt9211 *ctx = i2c_get_clientdata(client);769770drm_bridge_remove(&ctx->bridge);771}772773static const struct i2c_device_id lt9211_id[] = {774{ "lontium,lt9211" },775{},776};777MODULE_DEVICE_TABLE(i2c, lt9211_id);778779static const struct of_device_id lt9211_match_table[] = {780{ .compatible = "lontium,lt9211" },781{},782};783MODULE_DEVICE_TABLE(of, lt9211_match_table);784785static struct i2c_driver lt9211_driver = {786.probe = lt9211_probe,787.remove = lt9211_remove,788.id_table = lt9211_id,789.driver = {790.name = "lt9211",791.of_match_table = lt9211_match_table,792},793};794module_i2c_driver(lt9211_driver);795796MODULE_AUTHOR("Marek Vasut <[email protected]>");797MODULE_DESCRIPTION("Lontium LT9211 DSI/LVDS/DPI bridge driver");798MODULE_LICENSE("GPL");799800801