Path: blob/master/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
29286 views
// SPDX-License-Identifier: GPL-2.0+12/*3* Copyright 2022,2023 NXP4*/56#include <linux/bitfield.h>7#include <linux/bits.h>8#include <linux/clk.h>9#include <linux/delay.h>10#include <linux/math.h>11#include <linux/media-bus-format.h>12#include <linux/mfd/syscon.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/phy/phy.h>16#include <linux/phy/phy-mipi-dphy.h>17#include <linux/platform_device.h>18#include <linux/regmap.h>1920#include <drm/bridge/dw_mipi_dsi.h>21#include <drm/drm_bridge.h>22#include <drm/drm_mipi_dsi.h>23#include <drm/drm_modes.h>2425/* DPHY PLL configuration registers */26#define DSI_REG 0x4c27#define CFGCLKFREQRANGE_MASK GENMASK(5, 0)28#define CFGCLKFREQRANGE(x) FIELD_PREP(CFGCLKFREQRANGE_MASK, (x))29#define CLKSEL_MASK GENMASK(7, 6)30#define CLKSEL_STOP FIELD_PREP(CLKSEL_MASK, 0)31#define CLKSEL_GEN FIELD_PREP(CLKSEL_MASK, 1)32#define CLKSEL_EXT FIELD_PREP(CLKSEL_MASK, 2)33#define HSFREQRANGE_MASK GENMASK(14, 8)34#define HSFREQRANGE(x) FIELD_PREP(HSFREQRANGE_MASK, (x))35#define UPDATE_PLL BIT(17)36#define SHADOW_CLR BIT(18)37#define CLK_EXT BIT(19)3839#define DSI_WRITE_REG0 0x5040#define M_MASK GENMASK(9, 0)41#define M(x) FIELD_PREP(M_MASK, ((x) - 2))42#define N_MASK GENMASK(13, 10)43#define N(x) FIELD_PREP(N_MASK, ((x) - 1))44#define VCO_CTRL_MASK GENMASK(19, 14)45#define VCO_CTRL(x) FIELD_PREP(VCO_CTRL_MASK, (x))46#define PROP_CTRL_MASK GENMASK(25, 20)47#define PROP_CTRL(x) FIELD_PREP(PROP_CTRL_MASK, (x))48#define INT_CTRL_MASK GENMASK(31, 26)49#define INT_CTRL(x) FIELD_PREP(INT_CTRL_MASK, (x))5051#define DSI_WRITE_REG1 0x5452#define GMP_CTRL_MASK GENMASK(1, 0)53#define GMP_CTRL(x) FIELD_PREP(GMP_CTRL_MASK, (x))54#define CPBIAS_CTRL_MASK GENMASK(8, 2)55#define CPBIAS_CTRL(x) FIELD_PREP(CPBIAS_CTRL_MASK, (x))56#define PLL_SHADOW_CTRL BIT(9)5758/* display mux control register */59#define DISPLAY_MUX 0x6060#define MIPI_DSI_RGB666_MAP_CFG GENMASK(7, 6)61#define RGB666_CONFIG1 FIELD_PREP(MIPI_DSI_RGB666_MAP_CFG, 0)62#define RGB666_CONFIG2 FIELD_PREP(MIPI_DSI_RGB666_MAP_CFG, 1)63#define MIPI_DSI_RGB565_MAP_CFG GENMASK(5, 4)64#define RGB565_CONFIG1 FIELD_PREP(MIPI_DSI_RGB565_MAP_CFG, 0)65#define RGB565_CONFIG2 FIELD_PREP(MIPI_DSI_RGB565_MAP_CFG, 1)66#define RGB565_CONFIG3 FIELD_PREP(MIPI_DSI_RGB565_MAP_CFG, 2)67#define LCDIF_CROSS_LINE_PATTERN GENMASK(3, 0)68#define RGB888_TO_RGB888 FIELD_PREP(LCDIF_CROSS_LINE_PATTERN, 0)69#define RGB888_TO_RGB666 FIELD_PREP(LCDIF_CROSS_LINE_PATTERN, 6)70#define RGB565_TO_RGB565 FIELD_PREP(LCDIF_CROSS_LINE_PATTERN, 7)7172#define MHZ(x) ((x) * 1000000UL)7374#define REF_CLK_RATE_MAX MHZ(64)75#define REF_CLK_RATE_MIN MHZ(2)76#define FOUT_MAX MHZ(1250)77#define FOUT_MIN MHZ(40)78#define FVCO_DIV_FACTOR MHZ(80)7980#define MBPS(x) ((x) * 1000000UL)8182#define DATA_RATE_MAX_SPEED MBPS(2500)83#define DATA_RATE_MIN_SPEED MBPS(80)8485#define M_MAX 625UL86#define M_MIN 64UL8788#define N_MAX 16U89#define N_MIN 1U9091struct imx93_dsi {92struct device *dev;93struct regmap *regmap;94struct clk *clk_pixel;95struct clk *clk_ref;96struct clk *clk_cfg;97struct dw_mipi_dsi *dmd;98struct dw_mipi_dsi_plat_data pdata;99union phy_configure_opts phy_cfg;100unsigned long ref_clk_rate;101u32 format;102};103104struct dphy_pll_cfg {105u32 m; /* PLL Feedback Multiplication Ratio */106u32 n; /* PLL Input Frequency Division Ratio */107};108109struct dphy_pll_vco_prop {110unsigned long max_fout;111u8 vco_cntl;112u8 prop_cntl;113};114115struct dphy_pll_hsfreqrange {116unsigned long max_mbps;117u8 hsfreqrange;118};119120/* DPHY Databook Table 3-13 Charge-pump Programmability */121static const struct dphy_pll_vco_prop vco_prop_map[] = {122{ 55, 0x3f, 0x0d },123{ 82, 0x37, 0x0d },124{ 110, 0x2f, 0x0d },125{ 165, 0x27, 0x0d },126{ 220, 0x1f, 0x0d },127{ 330, 0x17, 0x0d },128{ 440, 0x0f, 0x0d },129{ 660, 0x07, 0x0d },130{ 1149, 0x03, 0x0d },131{ 1152, 0x01, 0x0d },132{ 1250, 0x01, 0x0e },133};134135/* DPHY Databook Table 5-7 Frequency Ranges and Defaults */136static const struct dphy_pll_hsfreqrange hsfreqrange_map[] = {137{ 89, 0x00 },138{ 99, 0x10 },139{ 109, 0x20 },140{ 119, 0x30 },141{ 129, 0x01 },142{ 139, 0x11 },143{ 149, 0x21 },144{ 159, 0x31 },145{ 169, 0x02 },146{ 179, 0x12 },147{ 189, 0x22 },148{ 204, 0x32 },149{ 219, 0x03 },150{ 234, 0x13 },151{ 249, 0x23 },152{ 274, 0x33 },153{ 299, 0x04 },154{ 324, 0x14 },155{ 349, 0x25 },156{ 399, 0x35 },157{ 449, 0x05 },158{ 499, 0x16 },159{ 549, 0x26 },160{ 599, 0x37 },161{ 649, 0x07 },162{ 699, 0x18 },163{ 749, 0x28 },164{ 799, 0x39 },165{ 849, 0x09 },166{ 899, 0x19 },167{ 949, 0x29 },168{ 999, 0x3a },169{ 1049, 0x0a },170{ 1099, 0x1a },171{ 1149, 0x2a },172{ 1199, 0x3b },173{ 1249, 0x0b },174{ 1299, 0x1b },175{ 1349, 0x2b },176{ 1399, 0x3c },177{ 1449, 0x0c },178{ 1499, 0x1c },179{ 1549, 0x2c },180{ 1599, 0x3d },181{ 1649, 0x0d },182{ 1699, 0x1d },183{ 1749, 0x2e },184{ 1799, 0x3e },185{ 1849, 0x0e },186{ 1899, 0x1e },187{ 1949, 0x2f },188{ 1999, 0x3f },189{ 2049, 0x0f },190{ 2099, 0x40 },191{ 2149, 0x41 },192{ 2199, 0x42 },193{ 2249, 0x43 },194{ 2299, 0x44 },195{ 2349, 0x45 },196{ 2399, 0x46 },197{ 2449, 0x47 },198{ 2499, 0x48 },199{ 2500, 0x49 },200};201202static void dphy_pll_write(struct imx93_dsi *dsi, unsigned int reg, u32 value)203{204int ret;205206ret = regmap_write(dsi->regmap, reg, value);207if (ret < 0)208dev_err(dsi->dev, "failed to write 0x%08x to pll reg 0x%x: %d\n",209value, reg, ret);210}211212static inline unsigned long data_rate_to_fout(unsigned long data_rate)213{214/* Fout is half of data rate */215return data_rate / 2;216}217218static int219dphy_pll_get_configure_from_opts(struct imx93_dsi *dsi,220struct phy_configure_opts_mipi_dphy *dphy_opts,221struct dphy_pll_cfg *cfg)222{223struct device *dev = dsi->dev;224unsigned long fin = dsi->ref_clk_rate;225unsigned long fout;226unsigned long best_fout = 0;227unsigned int fvco_div;228unsigned int min_n, max_n, n, best_n = UINT_MAX;229unsigned long m, best_m = 0;230unsigned long min_delta = ULONG_MAX;231unsigned long delta;232u64 tmp;233234if (dphy_opts->hs_clk_rate < DATA_RATE_MIN_SPEED ||235dphy_opts->hs_clk_rate > DATA_RATE_MAX_SPEED) {236dev_dbg(dev, "invalid data rate per lane: %lu\n",237dphy_opts->hs_clk_rate);238return -EINVAL;239}240241fout = data_rate_to_fout(dphy_opts->hs_clk_rate);242243/* DPHY Databook 3.3.6.1 Output Frequency */244/* Fout = Fvco / Fvco_div = (Fin * M) / (Fvco_div * N) */245/* Fvco_div could be 1/2/4/8 according to Fout range. */246fvco_div = 8UL / min(DIV_ROUND_UP(fout, FVCO_DIV_FACTOR), 8UL);247248/* limitation: 2MHz <= Fin / N <= 8MHz */249min_n = DIV_ROUND_UP_ULL((u64)fin, MHZ(8));250max_n = DIV_ROUND_DOWN_ULL((u64)fin, MHZ(2));251252/* clamp possible N(s) */253min_n = clamp(min_n, N_MIN, N_MAX);254max_n = clamp(max_n, N_MIN, N_MAX);255256dev_dbg(dev, "Fout = %lu, Fvco_div = %u, n_range = [%u, %u]\n",257fout, fvco_div, min_n, max_n);258259for (n = min_n; n <= max_n; n++) {260/* M = (Fout * N * Fvco_div) / Fin */261m = DIV_ROUND_CLOSEST(fout * n * fvco_div, fin);262263/* check M range */264if (m < M_MIN || m > M_MAX)265continue;266267/* calculate temporary Fout */268tmp = m * fin;269do_div(tmp, n * fvco_div);270if (tmp < FOUT_MIN || tmp > FOUT_MAX)271continue;272273delta = abs(fout - tmp);274if (delta < min_delta) {275best_n = n;276best_m = m;277min_delta = delta;278best_fout = tmp;279}280}281282if (best_fout) {283cfg->m = best_m;284cfg->n = best_n;285dev_dbg(dev, "best Fout = %lu, m = %u, n = %u\n",286best_fout, cfg->m, cfg->n);287} else {288dev_dbg(dev, "failed to find best Fout\n");289return -EINVAL;290}291292return 0;293}294295static void dphy_pll_clear_shadow(struct imx93_dsi *dsi)296{297/* Reference DPHY Databook Figure 3-3 Initialization Timing Diagram. */298/* Select clock generation first. */299dphy_pll_write(dsi, DSI_REG, CLKSEL_GEN);300301/* Clear shadow after clock selection is done a while. */302fsleep(1);303dphy_pll_write(dsi, DSI_REG, CLKSEL_GEN | SHADOW_CLR);304305/* A minimum pulse of 5ns on shadow_clear signal. */306fsleep(1);307dphy_pll_write(dsi, DSI_REG, CLKSEL_GEN);308}309310static unsigned long dphy_pll_get_cfgclkrange(struct imx93_dsi *dsi)311{312/*313* DPHY Databook Table 4-4 System Control Signals mentions an equation314* for cfgclkfreqrange[5:0].315*/316return (clk_get_rate(dsi->clk_cfg) / MHZ(1) - 17) * 4;317}318319static u8320dphy_pll_get_hsfreqrange(struct phy_configure_opts_mipi_dphy *dphy_opts)321{322unsigned long mbps = dphy_opts->hs_clk_rate / MHZ(1);323int i;324325for (i = 0; i < ARRAY_SIZE(hsfreqrange_map); i++)326if (mbps <= hsfreqrange_map[i].max_mbps)327return hsfreqrange_map[i].hsfreqrange;328329return 0;330}331332static u8 dphy_pll_get_vco(struct phy_configure_opts_mipi_dphy *dphy_opts)333{334unsigned long fout = data_rate_to_fout(dphy_opts->hs_clk_rate) / MHZ(1);335int i;336337for (i = 0; i < ARRAY_SIZE(vco_prop_map); i++)338if (fout <= vco_prop_map[i].max_fout)339return vco_prop_map[i].vco_cntl;340341return 0;342}343344static u8 dphy_pll_get_prop(struct phy_configure_opts_mipi_dphy *dphy_opts)345{346unsigned long fout = data_rate_to_fout(dphy_opts->hs_clk_rate) / MHZ(1);347int i;348349for (i = 0; i < ARRAY_SIZE(vco_prop_map); i++)350if (fout <= vco_prop_map[i].max_fout)351return vco_prop_map[i].prop_cntl;352353return 0;354}355356static int dphy_pll_update(struct imx93_dsi *dsi)357{358int ret;359360ret = regmap_update_bits(dsi->regmap, DSI_REG, UPDATE_PLL, UPDATE_PLL);361if (ret < 0) {362dev_err(dsi->dev, "failed to set UPDATE_PLL: %d\n", ret);363return ret;364}365366/*367* The updatepll signal should be asserted for a minimum of four clkin368* cycles, according to DPHY Databook Figure 3-3 Initialization Timing369* Diagram.370*/371fsleep(10);372373ret = regmap_update_bits(dsi->regmap, DSI_REG, UPDATE_PLL, 0);374if (ret < 0) {375dev_err(dsi->dev, "failed to clear UPDATE_PLL: %d\n", ret);376return ret;377}378379return 0;380}381382static int dphy_pll_configure(struct imx93_dsi *dsi, union phy_configure_opts *opts)383{384struct dphy_pll_cfg cfg = { 0 };385u32 val;386int ret;387388ret = dphy_pll_get_configure_from_opts(dsi, &opts->mipi_dphy, &cfg);389if (ret) {390dev_err(dsi->dev, "failed to get phy pll cfg %d\n", ret);391return ret;392}393394dphy_pll_clear_shadow(dsi);395396/* DSI_REG */397val = CLKSEL_GEN |398CFGCLKFREQRANGE(dphy_pll_get_cfgclkrange(dsi)) |399HSFREQRANGE(dphy_pll_get_hsfreqrange(&opts->mipi_dphy));400dphy_pll_write(dsi, DSI_REG, val);401402/* DSI_WRITE_REG0 */403val = M(cfg.m) | N(cfg.n) | INT_CTRL(0) |404VCO_CTRL(dphy_pll_get_vco(&opts->mipi_dphy)) |405PROP_CTRL(dphy_pll_get_prop(&opts->mipi_dphy));406dphy_pll_write(dsi, DSI_WRITE_REG0, val);407408/* DSI_WRITE_REG1 */409dphy_pll_write(dsi, DSI_WRITE_REG1, GMP_CTRL(1) | CPBIAS_CTRL(0x10));410411ret = clk_prepare_enable(dsi->clk_ref);412if (ret < 0) {413dev_err(dsi->dev, "failed to enable ref clock: %d\n", ret);414return ret;415}416417/*418* At least 10 refclk cycles are required before updatePLL assertion,419* according to DPHY Databook Figure 3-3 Initialization Timing Diagram.420*/421fsleep(10);422423ret = dphy_pll_update(dsi);424if (ret < 0) {425clk_disable_unprepare(dsi->clk_ref);426return ret;427}428429return 0;430}431432static void dphy_pll_clear_reg(struct imx93_dsi *dsi)433{434dphy_pll_write(dsi, DSI_REG, 0);435dphy_pll_write(dsi, DSI_WRITE_REG0, 0);436dphy_pll_write(dsi, DSI_WRITE_REG1, 0);437}438439static int dphy_pll_init(struct imx93_dsi *dsi)440{441int ret;442443ret = clk_prepare_enable(dsi->clk_cfg);444if (ret < 0) {445dev_err(dsi->dev, "failed to enable config clock: %d\n", ret);446return ret;447}448449dphy_pll_clear_reg(dsi);450451return 0;452}453454static void dphy_pll_uninit(struct imx93_dsi *dsi)455{456dphy_pll_clear_reg(dsi);457clk_disable_unprepare(dsi->clk_cfg);458}459460static void dphy_pll_power_off(struct imx93_dsi *dsi)461{462dphy_pll_clear_reg(dsi);463clk_disable_unprepare(dsi->clk_ref);464}465466static int imx93_dsi_get_phy_configure_opts(struct imx93_dsi *dsi,467const struct drm_display_mode *mode,468union phy_configure_opts *phy_cfg,469u32 lanes, u32 format)470{471struct device *dev = dsi->dev;472int bpp;473int ret;474475bpp = mipi_dsi_pixel_format_to_bpp(format);476if (bpp < 0) {477dev_dbg(dev, "failed to get bpp for pixel format %d\n", format);478return -EINVAL;479}480481ret = phy_mipi_dphy_get_default_config(mode->clock * MSEC_PER_SEC, bpp,482lanes, &phy_cfg->mipi_dphy);483if (ret < 0) {484dev_dbg(dev, "failed to get default phy cfg %d\n", ret);485return ret;486}487488return 0;489}490491static enum drm_mode_status492imx93_dsi_validate_mode(struct imx93_dsi *dsi, const struct drm_display_mode *mode)493{494struct drm_bridge *dmd_bridge = dw_mipi_dsi_get_bridge(dsi->dmd);495struct drm_bridge *last_bridge __free(drm_bridge_put) =496drm_bridge_chain_get_last_bridge(dmd_bridge->encoder);497498if ((last_bridge->ops & DRM_BRIDGE_OP_DETECT) &&499(last_bridge->ops & DRM_BRIDGE_OP_EDID)) {500unsigned long pixel_clock_rate = mode->clock * 1000;501unsigned long rounded_rate;502503/* Allow +/-0.5% pixel clock rate deviation */504rounded_rate = clk_round_rate(dsi->clk_pixel, pixel_clock_rate);505if (rounded_rate < pixel_clock_rate * 995 / 1000 ||506rounded_rate > pixel_clock_rate * 1005 / 1000) {507dev_dbg(dsi->dev, "failed to round clock for mode " DRM_MODE_FMT "\n",508DRM_MODE_ARG(mode));509return MODE_NOCLOCK;510}511}512513return MODE_OK;514}515516static enum drm_mode_status517imx93_dsi_validate_phy(struct imx93_dsi *dsi, const struct drm_display_mode *mode,518unsigned long mode_flags, u32 lanes, u32 format)519{520union phy_configure_opts phy_cfg;521struct dphy_pll_cfg cfg = { 0 };522struct device *dev = dsi->dev;523int ret;524525ret = imx93_dsi_get_phy_configure_opts(dsi, mode, &phy_cfg, lanes,526format);527if (ret < 0) {528dev_dbg(dev, "failed to get phy cfg opts %d\n", ret);529return MODE_ERROR;530}531532ret = dphy_pll_get_configure_from_opts(dsi, &phy_cfg.mipi_dphy, &cfg);533if (ret < 0) {534dev_dbg(dev, "failed to get phy pll cfg %d\n", ret);535return MODE_NOCLOCK;536}537538return MODE_OK;539}540541static enum drm_mode_status542imx93_dsi_mode_valid(void *priv_data, const struct drm_display_mode *mode,543unsigned long mode_flags, u32 lanes, u32 format)544{545struct imx93_dsi *dsi = priv_data;546struct device *dev = dsi->dev;547enum drm_mode_status ret;548549ret = imx93_dsi_validate_mode(dsi, mode);550if (ret != MODE_OK) {551dev_dbg(dev, "failed to validate mode " DRM_MODE_FMT "\n",552DRM_MODE_ARG(mode));553return ret;554}555556ret = imx93_dsi_validate_phy(dsi, mode, mode_flags, lanes, format);557if (ret != MODE_OK) {558dev_dbg(dev, "failed to validate phy for mode " DRM_MODE_FMT "\n",559DRM_MODE_ARG(mode));560return ret;561}562563return MODE_OK;564}565566static bool imx93_dsi_mode_fixup(void *priv_data,567const struct drm_display_mode *mode,568struct drm_display_mode *adjusted_mode)569{570struct imx93_dsi *dsi = priv_data;571unsigned long pixel_clock_rate;572unsigned long rounded_rate;573574pixel_clock_rate = mode->clock * 1000;575rounded_rate = clk_round_rate(dsi->clk_pixel, pixel_clock_rate);576577memcpy(adjusted_mode, mode, sizeof(*mode));578adjusted_mode->clock = rounded_rate / 1000;579580dev_dbg(dsi->dev, "adj clock %d for mode " DRM_MODE_FMT "\n",581adjusted_mode->clock, DRM_MODE_ARG(mode));582583return true;584}585586static u32 *imx93_dsi_get_input_bus_fmts(void *priv_data,587struct drm_bridge *bridge,588struct drm_bridge_state *bridge_state,589struct drm_crtc_state *crtc_state,590struct drm_connector_state *conn_state,591u32 output_fmt,592unsigned int *num_input_fmts)593{594u32 *input_fmts, input_fmt;595596*num_input_fmts = 0;597598switch (output_fmt) {599case MEDIA_BUS_FMT_RGB888_1X24:600case MEDIA_BUS_FMT_RGB666_1X18:601case MEDIA_BUS_FMT_FIXED:602input_fmt = MEDIA_BUS_FMT_RGB888_1X24;603break;604case MEDIA_BUS_FMT_RGB565_1X16:605input_fmt = output_fmt;606break;607default:608return NULL;609}610611input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);612if (!input_fmts)613return NULL;614input_fmts[0] = input_fmt;615*num_input_fmts = 1;616617return input_fmts;618}619620static int imx93_dsi_phy_init(void *priv_data)621{622struct imx93_dsi *dsi = priv_data;623unsigned int fmt = 0;624int ret;625626switch (dsi->format) {627case MIPI_DSI_FMT_RGB888:628fmt = RGB888_TO_RGB888;629break;630case MIPI_DSI_FMT_RGB666:631fmt = RGB888_TO_RGB666;632regmap_update_bits(dsi->regmap, DISPLAY_MUX,633MIPI_DSI_RGB666_MAP_CFG, RGB666_CONFIG2);634break;635case MIPI_DSI_FMT_RGB666_PACKED:636fmt = RGB888_TO_RGB666;637regmap_update_bits(dsi->regmap, DISPLAY_MUX,638MIPI_DSI_RGB666_MAP_CFG, RGB666_CONFIG1);639break;640case MIPI_DSI_FMT_RGB565:641fmt = RGB565_TO_RGB565;642regmap_update_bits(dsi->regmap, DISPLAY_MUX,643MIPI_DSI_RGB565_MAP_CFG, RGB565_CONFIG1);644break;645}646647regmap_update_bits(dsi->regmap, DISPLAY_MUX, LCDIF_CROSS_LINE_PATTERN, fmt);648649ret = dphy_pll_init(dsi);650if (ret < 0) {651dev_err(dsi->dev, "failed to init phy pll: %d\n", ret);652return ret;653}654655ret = dphy_pll_configure(dsi, &dsi->phy_cfg);656if (ret < 0) {657dev_err(dsi->dev, "failed to configure phy pll: %d\n", ret);658dphy_pll_uninit(dsi);659return ret;660}661662return 0;663}664665static void imx93_dsi_phy_power_off(void *priv_data)666{667struct imx93_dsi *dsi = priv_data;668669dphy_pll_power_off(dsi);670dphy_pll_uninit(dsi);671}672673static int674imx93_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,675unsigned long mode_flags, u32 lanes, u32 format,676unsigned int *lane_mbps)677{678struct imx93_dsi *dsi = priv_data;679union phy_configure_opts phy_cfg;680struct device *dev = dsi->dev;681int ret;682683ret = imx93_dsi_get_phy_configure_opts(dsi, mode, &phy_cfg, lanes,684format);685if (ret < 0) {686dev_dbg(dev, "failed to get phy cfg opts %d\n", ret);687return ret;688}689690*lane_mbps = DIV_ROUND_UP(phy_cfg.mipi_dphy.hs_clk_rate, USEC_PER_SEC);691692memcpy(&dsi->phy_cfg, &phy_cfg, sizeof(phy_cfg));693694dev_dbg(dev, "get lane_mbps %u for mode " DRM_MODE_FMT "\n",695*lane_mbps, DRM_MODE_ARG(mode));696697return 0;698}699700/* High-Speed Transition Times */701struct hstt {702unsigned int maxfreq;703struct dw_mipi_dsi_dphy_timing timing;704};705706#define HSTT(_maxfreq, _c_lp2hs, _c_hs2lp, _d_lp2hs, _d_hs2lp) \707{ \708.maxfreq = (_maxfreq), \709.timing = { \710.clk_lp2hs = (_c_lp2hs), \711.clk_hs2lp = (_c_hs2lp), \712.data_lp2hs = (_d_lp2hs), \713.data_hs2lp = (_d_hs2lp), \714} \715}716717/* DPHY Databook Table A-4 High-Speed Transition Times */718static const struct hstt hstt_table[] = {719HSTT(80, 21, 17, 15, 10),720HSTT(90, 23, 17, 16, 10),721HSTT(100, 22, 17, 16, 10),722HSTT(110, 25, 18, 17, 11),723HSTT(120, 26, 20, 18, 11),724HSTT(130, 27, 19, 19, 11),725HSTT(140, 27, 19, 19, 11),726HSTT(150, 28, 20, 20, 12),727HSTT(160, 30, 21, 22, 13),728HSTT(170, 30, 21, 23, 13),729HSTT(180, 31, 21, 23, 13),730HSTT(190, 32, 22, 24, 13),731HSTT(205, 35, 22, 25, 13),732HSTT(220, 37, 26, 27, 15),733HSTT(235, 38, 28, 27, 16),734HSTT(250, 41, 29, 30, 17),735HSTT(275, 43, 29, 32, 18),736HSTT(300, 45, 32, 35, 19),737HSTT(325, 48, 33, 36, 18),738HSTT(350, 51, 35, 40, 20),739HSTT(400, 59, 37, 44, 21),740HSTT(450, 65, 40, 49, 23),741HSTT(500, 71, 41, 54, 24),742HSTT(550, 77, 44, 57, 26),743HSTT(600, 82, 46, 64, 27),744HSTT(650, 87, 48, 67, 28),745HSTT(700, 94, 52, 71, 29),746HSTT(750, 99, 52, 75, 31),747HSTT(800, 105, 55, 82, 32),748HSTT(850, 110, 58, 85, 32),749HSTT(900, 115, 58, 88, 35),750HSTT(950, 120, 62, 93, 36),751HSTT(1000, 128, 63, 99, 38),752HSTT(1050, 132, 65, 102, 38),753HSTT(1100, 138, 67, 106, 39),754HSTT(1150, 146, 69, 112, 42),755HSTT(1200, 151, 71, 117, 43),756HSTT(1250, 153, 74, 120, 45),757HSTT(1300, 160, 73, 124, 46),758HSTT(1350, 165, 76, 130, 47),759HSTT(1400, 172, 78, 134, 49),760HSTT(1450, 177, 80, 138, 49),761HSTT(1500, 183, 81, 143, 52),762HSTT(1550, 191, 84, 147, 52),763HSTT(1600, 194, 85, 152, 52),764HSTT(1650, 201, 86, 155, 53),765HSTT(1700, 208, 88, 161, 53),766HSTT(1750, 212, 89, 165, 53),767HSTT(1800, 220, 90, 171, 54),768HSTT(1850, 223, 92, 175, 54),769HSTT(1900, 231, 91, 180, 55),770HSTT(1950, 236, 95, 185, 56),771HSTT(2000, 243, 97, 190, 56),772HSTT(2050, 248, 99, 194, 58),773HSTT(2100, 252, 100, 199, 59),774HSTT(2150, 259, 102, 204, 61),775HSTT(2200, 266, 105, 210, 62),776HSTT(2250, 269, 109, 213, 63),777HSTT(2300, 272, 109, 217, 65),778HSTT(2350, 281, 112, 225, 66),779HSTT(2400, 283, 115, 226, 66),780HSTT(2450, 282, 115, 226, 67),781HSTT(2500, 281, 118, 227, 67),782};783784static int imx93_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,785struct dw_mipi_dsi_dphy_timing *timing)786{787struct imx93_dsi *dsi = priv_data;788struct device *dev = dsi->dev;789int i;790791for (i = 0; i < ARRAY_SIZE(hstt_table); i++)792if (lane_mbps <= hstt_table[i].maxfreq)793break;794795if (i == ARRAY_SIZE(hstt_table)) {796dev_err(dev, "failed to get phy timing for lane_mbps %u\n",797lane_mbps);798return -EINVAL;799}800801*timing = hstt_table[i].timing;802803dev_dbg(dev, "get phy timing for %u <= %u (lane_mbps)\n",804lane_mbps, hstt_table[i].maxfreq);805806return 0;807}808809static const struct dw_mipi_dsi_phy_ops imx93_dsi_phy_ops = {810.init = imx93_dsi_phy_init,811.power_off = imx93_dsi_phy_power_off,812.get_lane_mbps = imx93_dsi_get_lane_mbps,813.get_timing = imx93_dsi_phy_get_timing,814};815816static int imx93_dsi_host_attach(void *priv_data, struct mipi_dsi_device *device)817{818struct imx93_dsi *dsi = priv_data;819820dsi->format = device->format;821822return 0;823}824825static const struct dw_mipi_dsi_host_ops imx93_dsi_host_ops = {826.attach = imx93_dsi_host_attach,827};828829static int imx93_dsi_probe(struct platform_device *pdev)830{831struct device *dev = &pdev->dev;832struct device_node *np = dev->of_node;833struct imx93_dsi *dsi;834int ret;835836dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);837if (!dsi)838return -ENOMEM;839840dsi->regmap = syscon_regmap_lookup_by_phandle(np, "fsl,media-blk-ctrl");841if (IS_ERR(dsi->regmap)) {842ret = PTR_ERR(dsi->regmap);843dev_err(dev, "failed to get block ctrl regmap: %d\n", ret);844return ret;845}846847dsi->clk_pixel = devm_clk_get(dev, "pix");848if (IS_ERR(dsi->clk_pixel))849return dev_err_probe(dev, PTR_ERR(dsi->clk_pixel),850"failed to get pixel clock\n");851852dsi->clk_cfg = devm_clk_get(dev, "phy_cfg");853if (IS_ERR(dsi->clk_cfg))854return dev_err_probe(dev, PTR_ERR(dsi->clk_cfg),855"failed to get phy cfg clock\n");856857dsi->clk_ref = devm_clk_get(dev, "phy_ref");858if (IS_ERR(dsi->clk_ref))859return dev_err_probe(dev, PTR_ERR(dsi->clk_ref),860"failed to get phy ref clock\n");861862dsi->ref_clk_rate = clk_get_rate(dsi->clk_ref);863if (dsi->ref_clk_rate < REF_CLK_RATE_MIN ||864dsi->ref_clk_rate > REF_CLK_RATE_MAX) {865dev_err(dev, "invalid phy ref clock rate %lu\n",866dsi->ref_clk_rate);867return -EINVAL;868}869dev_dbg(dev, "phy ref clock rate: %lu\n", dsi->ref_clk_rate);870871dsi->dev = dev;872dsi->pdata.max_data_lanes = 4;873dsi->pdata.mode_valid = imx93_dsi_mode_valid;874dsi->pdata.mode_fixup = imx93_dsi_mode_fixup;875dsi->pdata.get_input_bus_fmts = imx93_dsi_get_input_bus_fmts;876dsi->pdata.phy_ops = &imx93_dsi_phy_ops;877dsi->pdata.host_ops = &imx93_dsi_host_ops;878dsi->pdata.priv_data = dsi;879platform_set_drvdata(pdev, dsi);880881dsi->dmd = dw_mipi_dsi_probe(pdev, &dsi->pdata);882if (IS_ERR(dsi->dmd))883return dev_err_probe(dev, PTR_ERR(dsi->dmd),884"failed to probe dw_mipi_dsi\n");885886return 0;887}888889static void imx93_dsi_remove(struct platform_device *pdev)890{891struct imx93_dsi *dsi = platform_get_drvdata(pdev);892893dw_mipi_dsi_remove(dsi->dmd);894}895896static const struct of_device_id imx93_dsi_dt_ids[] = {897{ .compatible = "fsl,imx93-mipi-dsi", },898{ /* sentinel */ }899};900MODULE_DEVICE_TABLE(of, imx93_dsi_dt_ids);901902static struct platform_driver imx93_dsi_driver = {903.probe = imx93_dsi_probe,904.remove = imx93_dsi_remove,905.driver = {906.of_match_table = imx93_dsi_dt_ids,907.name = "imx93_mipi_dsi",908},909};910module_platform_driver(imx93_dsi_driver);911912MODULE_DESCRIPTION("Freescale i.MX93 MIPI DSI driver");913MODULE_AUTHOR("Liu Ying <[email protected]>");914MODULE_LICENSE("GPL");915916917