1*dec72739SThierry Reding /* 2*dec72739SThierry Reding * Copyright (C) 2013 NVIDIA Corporation 3*dec72739SThierry Reding * 4*dec72739SThierry Reding * Permission to use, copy, modify, distribute, and sell this software and its 5*dec72739SThierry Reding * documentation for any purpose is hereby granted without fee, provided that 6*dec72739SThierry Reding * the above copyright notice appear in all copies and that both that copyright 7*dec72739SThierry Reding * notice and this permission notice appear in supporting documentation, and 8*dec72739SThierry Reding * that the name of the copyright holders not be used in advertising or 9*dec72739SThierry Reding * publicity pertaining to distribution of the software without specific, 10*dec72739SThierry Reding * written prior permission. The copyright holders make no representations 11*dec72739SThierry Reding * about the suitability of this software for any purpose. It is provided "as 12*dec72739SThierry Reding * is" without express or implied warranty. 13*dec72739SThierry Reding * 14*dec72739SThierry Reding * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15*dec72739SThierry Reding * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16*dec72739SThierry Reding * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17*dec72739SThierry Reding * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18*dec72739SThierry Reding * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19*dec72739SThierry Reding * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20*dec72739SThierry Reding * OF THIS SOFTWARE. 21*dec72739SThierry Reding */ 22*dec72739SThierry Reding 23*dec72739SThierry Reding #include <linux/clk.h> 24*dec72739SThierry Reding #include <linux/debugfs.h> 25*dec72739SThierry Reding #include <linux/host1x.h> 26*dec72739SThierry Reding #include <linux/module.h> 27*dec72739SThierry Reding #include <linux/of.h> 28*dec72739SThierry Reding #include <linux/platform_device.h> 29*dec72739SThierry Reding #include <linux/reset.h> 30*dec72739SThierry Reding 31*dec72739SThierry Reding #include <drm/drm_mipi_dsi.h> 32*dec72739SThierry Reding #include <drm/drm_panel.h> 33*dec72739SThierry Reding 34*dec72739SThierry Reding #include <video/mipi_display.h> 35*dec72739SThierry Reding 36*dec72739SThierry Reding #include "dc.h" 37*dec72739SThierry Reding #include "drm.h" 38*dec72739SThierry Reding #include "dsi.h" 39*dec72739SThierry Reding #include "mipi-phy.h" 40*dec72739SThierry Reding 41*dec72739SThierry Reding #define DSI_VIDEO_FIFO_DEPTH (1920 / 4) 42*dec72739SThierry Reding #define DSI_HOST_FIFO_DEPTH 64 43*dec72739SThierry Reding 44*dec72739SThierry Reding struct tegra_dsi { 45*dec72739SThierry Reding struct host1x_client client; 46*dec72739SThierry Reding struct tegra_output output; 47*dec72739SThierry Reding struct device *dev; 48*dec72739SThierry Reding 49*dec72739SThierry Reding void __iomem *regs; 50*dec72739SThierry Reding 51*dec72739SThierry Reding struct reset_control *rst; 52*dec72739SThierry Reding struct clk *clk_parent; 53*dec72739SThierry Reding struct clk *clk_lp; 54*dec72739SThierry Reding struct clk *clk; 55*dec72739SThierry Reding 56*dec72739SThierry Reding struct drm_info_list *debugfs_files; 57*dec72739SThierry Reding struct drm_minor *minor; 58*dec72739SThierry Reding struct dentry *debugfs; 59*dec72739SThierry Reding 60*dec72739SThierry Reding enum mipi_dsi_pixel_format format; 61*dec72739SThierry Reding unsigned int lanes; 62*dec72739SThierry Reding 63*dec72739SThierry Reding struct tegra_mipi_device *mipi; 64*dec72739SThierry Reding struct mipi_dsi_host host; 65*dec72739SThierry Reding }; 66*dec72739SThierry Reding 67*dec72739SThierry Reding static inline struct tegra_dsi * 68*dec72739SThierry Reding host1x_client_to_dsi(struct host1x_client *client) 69*dec72739SThierry Reding { 70*dec72739SThierry Reding return container_of(client, struct tegra_dsi, client); 71*dec72739SThierry Reding } 72*dec72739SThierry Reding 73*dec72739SThierry Reding static inline struct tegra_dsi *host_to_tegra(struct mipi_dsi_host *host) 74*dec72739SThierry Reding { 75*dec72739SThierry Reding return container_of(host, struct tegra_dsi, host); 76*dec72739SThierry Reding } 77*dec72739SThierry Reding 78*dec72739SThierry Reding static inline struct tegra_dsi *to_dsi(struct tegra_output *output) 79*dec72739SThierry Reding { 80*dec72739SThierry Reding return container_of(output, struct tegra_dsi, output); 81*dec72739SThierry Reding } 82*dec72739SThierry Reding 83*dec72739SThierry Reding static inline unsigned long tegra_dsi_readl(struct tegra_dsi *dsi, 84*dec72739SThierry Reding unsigned long reg) 85*dec72739SThierry Reding { 86*dec72739SThierry Reding return readl(dsi->regs + (reg << 2)); 87*dec72739SThierry Reding } 88*dec72739SThierry Reding 89*dec72739SThierry Reding static inline void tegra_dsi_writel(struct tegra_dsi *dsi, unsigned long value, 90*dec72739SThierry Reding unsigned long reg) 91*dec72739SThierry Reding { 92*dec72739SThierry Reding writel(value, dsi->regs + (reg << 2)); 93*dec72739SThierry Reding } 94*dec72739SThierry Reding 95*dec72739SThierry Reding static int tegra_dsi_show_regs(struct seq_file *s, void *data) 96*dec72739SThierry Reding { 97*dec72739SThierry Reding struct drm_info_node *node = s->private; 98*dec72739SThierry Reding struct tegra_dsi *dsi = node->info_ent->data; 99*dec72739SThierry Reding 100*dec72739SThierry Reding #define DUMP_REG(name) \ 101*dec72739SThierry Reding seq_printf(s, "%-32s %#05x %08lx\n", #name, name, \ 102*dec72739SThierry Reding tegra_dsi_readl(dsi, name)) 103*dec72739SThierry Reding 104*dec72739SThierry Reding DUMP_REG(DSI_INCR_SYNCPT); 105*dec72739SThierry Reding DUMP_REG(DSI_INCR_SYNCPT_CONTROL); 106*dec72739SThierry Reding DUMP_REG(DSI_INCR_SYNCPT_ERROR); 107*dec72739SThierry Reding DUMP_REG(DSI_CTXSW); 108*dec72739SThierry Reding DUMP_REG(DSI_RD_DATA); 109*dec72739SThierry Reding DUMP_REG(DSI_WR_DATA); 110*dec72739SThierry Reding DUMP_REG(DSI_POWER_CONTROL); 111*dec72739SThierry Reding DUMP_REG(DSI_INT_ENABLE); 112*dec72739SThierry Reding DUMP_REG(DSI_INT_STATUS); 113*dec72739SThierry Reding DUMP_REG(DSI_INT_MASK); 114*dec72739SThierry Reding DUMP_REG(DSI_HOST_CONTROL); 115*dec72739SThierry Reding DUMP_REG(DSI_CONTROL); 116*dec72739SThierry Reding DUMP_REG(DSI_SOL_DELAY); 117*dec72739SThierry Reding DUMP_REG(DSI_MAX_THRESHOLD); 118*dec72739SThierry Reding DUMP_REG(DSI_TRIGGER); 119*dec72739SThierry Reding DUMP_REG(DSI_TX_CRC); 120*dec72739SThierry Reding DUMP_REG(DSI_STATUS); 121*dec72739SThierry Reding 122*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_CONTROL); 123*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_0); 124*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_1); 125*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_2); 126*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_3); 127*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_4); 128*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_5); 129*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_6); 130*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_7); 131*dec72739SThierry Reding 132*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_0_LO); 133*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_0_HI); 134*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_1_LO); 135*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_1_HI); 136*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_2_LO); 137*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_2_HI); 138*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_3_LO); 139*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_3_HI); 140*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_4_LO); 141*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_4_HI); 142*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_5_LO); 143*dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_5_HI); 144*dec72739SThierry Reding 145*dec72739SThierry Reding DUMP_REG(DSI_DCS_CMDS); 146*dec72739SThierry Reding 147*dec72739SThierry Reding DUMP_REG(DSI_PKT_LEN_0_1); 148*dec72739SThierry Reding DUMP_REG(DSI_PKT_LEN_2_3); 149*dec72739SThierry Reding DUMP_REG(DSI_PKT_LEN_4_5); 150*dec72739SThierry Reding DUMP_REG(DSI_PKT_LEN_6_7); 151*dec72739SThierry Reding 152*dec72739SThierry Reding DUMP_REG(DSI_PHY_TIMING_0); 153*dec72739SThierry Reding DUMP_REG(DSI_PHY_TIMING_1); 154*dec72739SThierry Reding DUMP_REG(DSI_PHY_TIMING_2); 155*dec72739SThierry Reding DUMP_REG(DSI_BTA_TIMING); 156*dec72739SThierry Reding 157*dec72739SThierry Reding DUMP_REG(DSI_TIMEOUT_0); 158*dec72739SThierry Reding DUMP_REG(DSI_TIMEOUT_1); 159*dec72739SThierry Reding DUMP_REG(DSI_TO_TALLY); 160*dec72739SThierry Reding 161*dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_0); 162*dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_CD); 163*dec72739SThierry Reding DUMP_REG(DSI_PAD_CD_STATUS); 164*dec72739SThierry Reding DUMP_REG(DSI_VIDEO_MODE_CONTROL); 165*dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_1); 166*dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_2); 167*dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_3); 168*dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_4); 169*dec72739SThierry Reding 170*dec72739SThierry Reding DUMP_REG(DSI_GANGED_MODE_CONTROL); 171*dec72739SThierry Reding DUMP_REG(DSI_GANGED_MODE_START); 172*dec72739SThierry Reding DUMP_REG(DSI_GANGED_MODE_SIZE); 173*dec72739SThierry Reding 174*dec72739SThierry Reding DUMP_REG(DSI_RAW_DATA_BYTE_COUNT); 175*dec72739SThierry Reding DUMP_REG(DSI_ULTRA_LOW_POWER_CONTROL); 176*dec72739SThierry Reding 177*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_8); 178*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_9); 179*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_10); 180*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_11); 181*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_12); 182*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_13); 183*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_14); 184*dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_15); 185*dec72739SThierry Reding 186*dec72739SThierry Reding #undef DUMP_REG 187*dec72739SThierry Reding 188*dec72739SThierry Reding return 0; 189*dec72739SThierry Reding } 190*dec72739SThierry Reding 191*dec72739SThierry Reding static struct drm_info_list debugfs_files[] = { 192*dec72739SThierry Reding { "regs", tegra_dsi_show_regs, 0, NULL }, 193*dec72739SThierry Reding }; 194*dec72739SThierry Reding 195*dec72739SThierry Reding static int tegra_dsi_debugfs_init(struct tegra_dsi *dsi, 196*dec72739SThierry Reding struct drm_minor *minor) 197*dec72739SThierry Reding { 198*dec72739SThierry Reding const char *name = dev_name(dsi->dev); 199*dec72739SThierry Reding unsigned int i; 200*dec72739SThierry Reding int err; 201*dec72739SThierry Reding 202*dec72739SThierry Reding dsi->debugfs = debugfs_create_dir(name, minor->debugfs_root); 203*dec72739SThierry Reding if (!dsi->debugfs) 204*dec72739SThierry Reding return -ENOMEM; 205*dec72739SThierry Reding 206*dec72739SThierry Reding dsi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files), 207*dec72739SThierry Reding GFP_KERNEL); 208*dec72739SThierry Reding if (!dsi->debugfs_files) { 209*dec72739SThierry Reding err = -ENOMEM; 210*dec72739SThierry Reding goto remove; 211*dec72739SThierry Reding } 212*dec72739SThierry Reding 213*dec72739SThierry Reding for (i = 0; i < ARRAY_SIZE(debugfs_files); i++) 214*dec72739SThierry Reding dsi->debugfs_files[i].data = dsi; 215*dec72739SThierry Reding 216*dec72739SThierry Reding err = drm_debugfs_create_files(dsi->debugfs_files, 217*dec72739SThierry Reding ARRAY_SIZE(debugfs_files), 218*dec72739SThierry Reding dsi->debugfs, minor); 219*dec72739SThierry Reding if (err < 0) 220*dec72739SThierry Reding goto free; 221*dec72739SThierry Reding 222*dec72739SThierry Reding dsi->minor = minor; 223*dec72739SThierry Reding 224*dec72739SThierry Reding return 0; 225*dec72739SThierry Reding 226*dec72739SThierry Reding free: 227*dec72739SThierry Reding kfree(dsi->debugfs_files); 228*dec72739SThierry Reding dsi->debugfs_files = NULL; 229*dec72739SThierry Reding remove: 230*dec72739SThierry Reding debugfs_remove(dsi->debugfs); 231*dec72739SThierry Reding dsi->debugfs = NULL; 232*dec72739SThierry Reding 233*dec72739SThierry Reding return err; 234*dec72739SThierry Reding } 235*dec72739SThierry Reding 236*dec72739SThierry Reding static int tegra_dsi_debugfs_exit(struct tegra_dsi *dsi) 237*dec72739SThierry Reding { 238*dec72739SThierry Reding drm_debugfs_remove_files(dsi->debugfs_files, ARRAY_SIZE(debugfs_files), 239*dec72739SThierry Reding dsi->minor); 240*dec72739SThierry Reding dsi->minor = NULL; 241*dec72739SThierry Reding 242*dec72739SThierry Reding kfree(dsi->debugfs_files); 243*dec72739SThierry Reding dsi->debugfs_files = NULL; 244*dec72739SThierry Reding 245*dec72739SThierry Reding debugfs_remove(dsi->debugfs); 246*dec72739SThierry Reding dsi->debugfs = NULL; 247*dec72739SThierry Reding 248*dec72739SThierry Reding return 0; 249*dec72739SThierry Reding } 250*dec72739SThierry Reding 251*dec72739SThierry Reding #define PKT_ID0(id) ((((id) & 0x3f) << 3) | (1 << 9)) 252*dec72739SThierry Reding #define PKT_LEN0(len) (((len) & 0x07) << 0) 253*dec72739SThierry Reding #define PKT_ID1(id) ((((id) & 0x3f) << 13) | (1 << 19)) 254*dec72739SThierry Reding #define PKT_LEN1(len) (((len) & 0x07) << 10) 255*dec72739SThierry Reding #define PKT_ID2(id) ((((id) & 0x3f) << 23) | (1 << 29)) 256*dec72739SThierry Reding #define PKT_LEN2(len) (((len) & 0x07) << 20) 257*dec72739SThierry Reding 258*dec72739SThierry Reding #define PKT_LP (1 << 30) 259*dec72739SThierry Reding #define NUM_PKT_SEQ 12 260*dec72739SThierry Reding 261*dec72739SThierry Reding /* non-burst mode with sync-end */ 262*dec72739SThierry Reding static const u32 pkt_seq_vnb_syne[NUM_PKT_SEQ] = { 263*dec72739SThierry Reding [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) | 264*dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 265*dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 266*dec72739SThierry Reding PKT_LP, 267*dec72739SThierry Reding [ 1] = 0, 268*dec72739SThierry Reding [ 2] = PKT_ID0(MIPI_DSI_V_SYNC_END) | PKT_LEN0(0) | 269*dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 270*dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 271*dec72739SThierry Reding PKT_LP, 272*dec72739SThierry Reding [ 3] = 0, 273*dec72739SThierry Reding [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 274*dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 275*dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 276*dec72739SThierry Reding PKT_LP, 277*dec72739SThierry Reding [ 5] = 0, 278*dec72739SThierry Reding [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 279*dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 280*dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0), 281*dec72739SThierry Reding [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) | 282*dec72739SThierry Reding PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) | 283*dec72739SThierry Reding PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4), 284*dec72739SThierry Reding [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 285*dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 286*dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 287*dec72739SThierry Reding PKT_LP, 288*dec72739SThierry Reding [ 9] = 0, 289*dec72739SThierry Reding [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 290*dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 291*dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0), 292*dec72739SThierry Reding [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) | 293*dec72739SThierry Reding PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) | 294*dec72739SThierry Reding PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4), 295*dec72739SThierry Reding }; 296*dec72739SThierry Reding 297*dec72739SThierry Reding static int tegra_dsi_set_phy_timing(struct tegra_dsi *dsi) 298*dec72739SThierry Reding { 299*dec72739SThierry Reding struct mipi_dphy_timing timing; 300*dec72739SThierry Reding unsigned long value, period; 301*dec72739SThierry Reding long rate; 302*dec72739SThierry Reding int err; 303*dec72739SThierry Reding 304*dec72739SThierry Reding rate = clk_get_rate(dsi->clk); 305*dec72739SThierry Reding if (rate < 0) 306*dec72739SThierry Reding return rate; 307*dec72739SThierry Reding 308*dec72739SThierry Reding period = DIV_ROUND_CLOSEST(1000000000UL, rate * 2); 309*dec72739SThierry Reding 310*dec72739SThierry Reding err = mipi_dphy_timing_get_default(&timing, period); 311*dec72739SThierry Reding if (err < 0) 312*dec72739SThierry Reding return err; 313*dec72739SThierry Reding 314*dec72739SThierry Reding err = mipi_dphy_timing_validate(&timing, period); 315*dec72739SThierry Reding if (err < 0) { 316*dec72739SThierry Reding dev_err(dsi->dev, "failed to validate D-PHY timing: %d\n", err); 317*dec72739SThierry Reding return err; 318*dec72739SThierry Reding } 319*dec72739SThierry Reding 320*dec72739SThierry Reding /* 321*dec72739SThierry Reding * The D-PHY timing fields below are expressed in byte-clock cycles, 322*dec72739SThierry Reding * so multiply the period by 8. 323*dec72739SThierry Reding */ 324*dec72739SThierry Reding period *= 8; 325*dec72739SThierry Reding 326*dec72739SThierry Reding value = DSI_TIMING_FIELD(timing.hsexit, period, 1) << 24 | 327*dec72739SThierry Reding DSI_TIMING_FIELD(timing.hstrail, period, 0) << 16 | 328*dec72739SThierry Reding DSI_TIMING_FIELD(timing.hszero, period, 3) << 8 | 329*dec72739SThierry Reding DSI_TIMING_FIELD(timing.hsprepare, period, 1); 330*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_0); 331*dec72739SThierry Reding 332*dec72739SThierry Reding value = DSI_TIMING_FIELD(timing.clktrail, period, 1) << 24 | 333*dec72739SThierry Reding DSI_TIMING_FIELD(timing.clkpost, period, 1) << 16 | 334*dec72739SThierry Reding DSI_TIMING_FIELD(timing.clkzero, period, 1) << 8 | 335*dec72739SThierry Reding DSI_TIMING_FIELD(timing.lpx, period, 1); 336*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_1); 337*dec72739SThierry Reding 338*dec72739SThierry Reding value = DSI_TIMING_FIELD(timing.clkprepare, period, 1) << 16 | 339*dec72739SThierry Reding DSI_TIMING_FIELD(timing.clkpre, period, 1) << 8 | 340*dec72739SThierry Reding DSI_TIMING_FIELD(0xff * period, period, 0) << 0; 341*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_2); 342*dec72739SThierry Reding 343*dec72739SThierry Reding value = DSI_TIMING_FIELD(timing.taget, period, 1) << 16 | 344*dec72739SThierry Reding DSI_TIMING_FIELD(timing.tasure, period, 1) << 8 | 345*dec72739SThierry Reding DSI_TIMING_FIELD(timing.tago, period, 1); 346*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_BTA_TIMING); 347*dec72739SThierry Reding 348*dec72739SThierry Reding return 0; 349*dec72739SThierry Reding } 350*dec72739SThierry Reding 351*dec72739SThierry Reding static int tegra_dsi_get_muldiv(enum mipi_dsi_pixel_format format, 352*dec72739SThierry Reding unsigned int *mulp, unsigned int *divp) 353*dec72739SThierry Reding { 354*dec72739SThierry Reding switch (format) { 355*dec72739SThierry Reding case MIPI_DSI_FMT_RGB666_PACKED: 356*dec72739SThierry Reding case MIPI_DSI_FMT_RGB888: 357*dec72739SThierry Reding *mulp = 3; 358*dec72739SThierry Reding *divp = 1; 359*dec72739SThierry Reding break; 360*dec72739SThierry Reding 361*dec72739SThierry Reding case MIPI_DSI_FMT_RGB565: 362*dec72739SThierry Reding *mulp = 2; 363*dec72739SThierry Reding *divp = 1; 364*dec72739SThierry Reding break; 365*dec72739SThierry Reding 366*dec72739SThierry Reding case MIPI_DSI_FMT_RGB666: 367*dec72739SThierry Reding *mulp = 9; 368*dec72739SThierry Reding *divp = 4; 369*dec72739SThierry Reding break; 370*dec72739SThierry Reding 371*dec72739SThierry Reding default: 372*dec72739SThierry Reding return -EINVAL; 373*dec72739SThierry Reding } 374*dec72739SThierry Reding 375*dec72739SThierry Reding return 0; 376*dec72739SThierry Reding } 377*dec72739SThierry Reding 378*dec72739SThierry Reding static int tegra_output_dsi_enable(struct tegra_output *output) 379*dec72739SThierry Reding { 380*dec72739SThierry Reding struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); 381*dec72739SThierry Reding struct drm_display_mode *mode = &dc->base.mode; 382*dec72739SThierry Reding unsigned int hact, hsw, hbp, hfp, i, mul, div; 383*dec72739SThierry Reding struct tegra_dsi *dsi = to_dsi(output); 384*dec72739SThierry Reding /* FIXME: don't hardcode this */ 385*dec72739SThierry Reding const u32 *pkt_seq = pkt_seq_vnb_syne; 386*dec72739SThierry Reding unsigned long value; 387*dec72739SThierry Reding int err; 388*dec72739SThierry Reding 389*dec72739SThierry Reding err = tegra_dsi_get_muldiv(dsi->format, &mul, &div); 390*dec72739SThierry Reding if (err < 0) 391*dec72739SThierry Reding return err; 392*dec72739SThierry Reding 393*dec72739SThierry Reding err = clk_enable(dsi->clk); 394*dec72739SThierry Reding if (err < 0) 395*dec72739SThierry Reding return err; 396*dec72739SThierry Reding 397*dec72739SThierry Reding reset_control_deassert(dsi->rst); 398*dec72739SThierry Reding 399*dec72739SThierry Reding value = DSI_CONTROL_CHANNEL(0) | DSI_CONTROL_FORMAT(dsi->format) | 400*dec72739SThierry Reding DSI_CONTROL_LANES(dsi->lanes - 1) | 401*dec72739SThierry Reding DSI_CONTROL_SOURCE(dc->pipe); 402*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_CONTROL); 403*dec72739SThierry Reding 404*dec72739SThierry Reding tegra_dsi_writel(dsi, DSI_VIDEO_FIFO_DEPTH, DSI_MAX_THRESHOLD); 405*dec72739SThierry Reding 406*dec72739SThierry Reding value = DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | 407*dec72739SThierry Reding DSI_HOST_CONTROL_ECC; 408*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 409*dec72739SThierry Reding 410*dec72739SThierry Reding value = tegra_dsi_readl(dsi, DSI_CONTROL); 411*dec72739SThierry Reding value |= DSI_CONTROL_HS_CLK_CTRL; 412*dec72739SThierry Reding value &= ~DSI_CONTROL_TX_TRIG(3); 413*dec72739SThierry Reding value &= ~DSI_CONTROL_DCS_ENABLE; 414*dec72739SThierry Reding value |= DSI_CONTROL_VIDEO_ENABLE; 415*dec72739SThierry Reding value &= ~DSI_CONTROL_HOST_ENABLE; 416*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_CONTROL); 417*dec72739SThierry Reding 418*dec72739SThierry Reding err = tegra_dsi_set_phy_timing(dsi); 419*dec72739SThierry Reding if (err < 0) 420*dec72739SThierry Reding return err; 421*dec72739SThierry Reding 422*dec72739SThierry Reding for (i = 0; i < NUM_PKT_SEQ; i++) 423*dec72739SThierry Reding tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i); 424*dec72739SThierry Reding 425*dec72739SThierry Reding /* horizontal active pixels */ 426*dec72739SThierry Reding hact = mode->hdisplay * mul / div; 427*dec72739SThierry Reding 428*dec72739SThierry Reding /* horizontal sync width */ 429*dec72739SThierry Reding hsw = (mode->hsync_end - mode->hsync_start) * mul / div; 430*dec72739SThierry Reding hsw -= 10; 431*dec72739SThierry Reding 432*dec72739SThierry Reding /* horizontal back porch */ 433*dec72739SThierry Reding hbp = (mode->htotal - mode->hsync_end) * mul / div; 434*dec72739SThierry Reding hbp -= 14; 435*dec72739SThierry Reding 436*dec72739SThierry Reding /* horizontal front porch */ 437*dec72739SThierry Reding hfp = (mode->hsync_start - mode->hdisplay) * mul / div; 438*dec72739SThierry Reding hfp -= 8; 439*dec72739SThierry Reding 440*dec72739SThierry Reding tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1); 441*dec72739SThierry Reding tegra_dsi_writel(dsi, hact << 16 | hbp, DSI_PKT_LEN_2_3); 442*dec72739SThierry Reding tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5); 443*dec72739SThierry Reding tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7); 444*dec72739SThierry Reding 445*dec72739SThierry Reding /* set SOL delay */ 446*dec72739SThierry Reding tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY); 447*dec72739SThierry Reding 448*dec72739SThierry Reding /* enable display controller */ 449*dec72739SThierry Reding value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 450*dec72739SThierry Reding value |= DSI_ENABLE; 451*dec72739SThierry Reding tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 452*dec72739SThierry Reding 453*dec72739SThierry Reding value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | 454*dec72739SThierry Reding PW4_ENABLE | PM0_ENABLE | PM1_ENABLE; 455*dec72739SThierry Reding tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); 456*dec72739SThierry Reding 457*dec72739SThierry Reding value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); 458*dec72739SThierry Reding value &= ~DISP_CTRL_MODE_MASK; 459*dec72739SThierry Reding value |= DISP_CTRL_MODE_C_DISPLAY; 460*dec72739SThierry Reding tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); 461*dec72739SThierry Reding 462*dec72739SThierry Reding tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); 463*dec72739SThierry Reding tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); 464*dec72739SThierry Reding 465*dec72739SThierry Reding /* enable DSI controller */ 466*dec72739SThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 467*dec72739SThierry Reding value |= DSI_POWER_CONTROL_ENABLE; 468*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 469*dec72739SThierry Reding 470*dec72739SThierry Reding return 0; 471*dec72739SThierry Reding } 472*dec72739SThierry Reding 473*dec72739SThierry Reding static int tegra_output_dsi_disable(struct tegra_output *output) 474*dec72739SThierry Reding { 475*dec72739SThierry Reding struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); 476*dec72739SThierry Reding struct tegra_dsi *dsi = to_dsi(output); 477*dec72739SThierry Reding unsigned long value; 478*dec72739SThierry Reding 479*dec72739SThierry Reding /* disable DSI controller */ 480*dec72739SThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 481*dec72739SThierry Reding value &= DSI_POWER_CONTROL_ENABLE; 482*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 483*dec72739SThierry Reding 484*dec72739SThierry Reding /* 485*dec72739SThierry Reding * FIXME: The output isn't attached to any CRTC when it's being 486*dec72739SThierry Reding * disabled, so the following will never be executed. 487*dec72739SThierry Reding */ 488*dec72739SThierry Reding if (dc) { 489*dec72739SThierry Reding /* disable display controller */ 490*dec72739SThierry Reding value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); 491*dec72739SThierry Reding value &= ~DISP_CTRL_MODE_MASK; 492*dec72739SThierry Reding tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); 493*dec72739SThierry Reding 494*dec72739SThierry Reding value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 495*dec72739SThierry Reding value &= ~DSI_ENABLE; 496*dec72739SThierry Reding tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 497*dec72739SThierry Reding } 498*dec72739SThierry Reding 499*dec72739SThierry Reding clk_disable(dsi->clk); 500*dec72739SThierry Reding 501*dec72739SThierry Reding return 0; 502*dec72739SThierry Reding } 503*dec72739SThierry Reding 504*dec72739SThierry Reding static int tegra_output_dsi_setup_clock(struct tegra_output *output, 505*dec72739SThierry Reding struct clk *clk, unsigned long pclk) 506*dec72739SThierry Reding { 507*dec72739SThierry Reding struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); 508*dec72739SThierry Reding struct drm_display_mode *mode = &dc->base.mode; 509*dec72739SThierry Reding unsigned int timeout, mul, div, vrefresh; 510*dec72739SThierry Reding struct tegra_dsi *dsi = to_dsi(output); 511*dec72739SThierry Reding unsigned long bclk, plld, value; 512*dec72739SThierry Reding struct clk *base; 513*dec72739SThierry Reding int err; 514*dec72739SThierry Reding 515*dec72739SThierry Reding err = tegra_dsi_get_muldiv(dsi->format, &mul, &div); 516*dec72739SThierry Reding if (err < 0) 517*dec72739SThierry Reding return err; 518*dec72739SThierry Reding 519*dec72739SThierry Reding vrefresh = drm_mode_vrefresh(mode); 520*dec72739SThierry Reding 521*dec72739SThierry Reding pclk = mode->htotal * mode->vtotal * vrefresh; 522*dec72739SThierry Reding bclk = (pclk * mul) / (div * dsi->lanes); 523*dec72739SThierry Reding plld = DIV_ROUND_UP(bclk * 8, 1000000); 524*dec72739SThierry Reding pclk = (plld * 1000000) / 2; 525*dec72739SThierry Reding 526*dec72739SThierry Reding err = clk_set_parent(clk, dsi->clk_parent); 527*dec72739SThierry Reding if (err < 0) { 528*dec72739SThierry Reding dev_err(dsi->dev, "failed to set parent clock: %d\n", err); 529*dec72739SThierry Reding return err; 530*dec72739SThierry Reding } 531*dec72739SThierry Reding 532*dec72739SThierry Reding base = clk_get_parent(dsi->clk_parent); 533*dec72739SThierry Reding 534*dec72739SThierry Reding /* 535*dec72739SThierry Reding * This assumes that the parent clock is pll_d_out0 or pll_d2_out 536*dec72739SThierry Reding * respectively, each of which divides the base pll_d by 2. 537*dec72739SThierry Reding */ 538*dec72739SThierry Reding err = clk_set_rate(base, pclk * 2); 539*dec72739SThierry Reding if (err < 0) { 540*dec72739SThierry Reding dev_err(dsi->dev, "failed to set base clock rate to %lu Hz\n", 541*dec72739SThierry Reding pclk * 2); 542*dec72739SThierry Reding return err; 543*dec72739SThierry Reding } 544*dec72739SThierry Reding 545*dec72739SThierry Reding /* 546*dec72739SThierry Reding * XXX: Move the below somewhere else so that we don't need to have 547*dec72739SThierry Reding * access to the vrefresh in this function? 548*dec72739SThierry Reding */ 549*dec72739SThierry Reding 550*dec72739SThierry Reding /* one frame high-speed transmission timeout */ 551*dec72739SThierry Reding timeout = (bclk / vrefresh) / 512; 552*dec72739SThierry Reding value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout); 553*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0); 554*dec72739SThierry Reding 555*dec72739SThierry Reding /* 2 ms peripheral timeout for panel */ 556*dec72739SThierry Reding timeout = 2 * bclk / 512 * 1000; 557*dec72739SThierry Reding value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000); 558*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1); 559*dec72739SThierry Reding 560*dec72739SThierry Reding value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0); 561*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_TO_TALLY); 562*dec72739SThierry Reding 563*dec72739SThierry Reding return 0; 564*dec72739SThierry Reding } 565*dec72739SThierry Reding 566*dec72739SThierry Reding static int tegra_output_dsi_check_mode(struct tegra_output *output, 567*dec72739SThierry Reding struct drm_display_mode *mode, 568*dec72739SThierry Reding enum drm_mode_status *status) 569*dec72739SThierry Reding { 570*dec72739SThierry Reding /* 571*dec72739SThierry Reding * FIXME: For now, always assume that the mode is okay. 572*dec72739SThierry Reding */ 573*dec72739SThierry Reding 574*dec72739SThierry Reding *status = MODE_OK; 575*dec72739SThierry Reding 576*dec72739SThierry Reding return 0; 577*dec72739SThierry Reding } 578*dec72739SThierry Reding 579*dec72739SThierry Reding static const struct tegra_output_ops dsi_ops = { 580*dec72739SThierry Reding .enable = tegra_output_dsi_enable, 581*dec72739SThierry Reding .disable = tegra_output_dsi_disable, 582*dec72739SThierry Reding .setup_clock = tegra_output_dsi_setup_clock, 583*dec72739SThierry Reding .check_mode = tegra_output_dsi_check_mode, 584*dec72739SThierry Reding }; 585*dec72739SThierry Reding 586*dec72739SThierry Reding static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) 587*dec72739SThierry Reding { 588*dec72739SThierry Reding unsigned long value; 589*dec72739SThierry Reding 590*dec72739SThierry Reding value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); 591*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0); 592*dec72739SThierry Reding 593*dec72739SThierry Reding return 0; 594*dec72739SThierry Reding } 595*dec72739SThierry Reding 596*dec72739SThierry Reding static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) 597*dec72739SThierry Reding { 598*dec72739SThierry Reding unsigned long value; 599*dec72739SThierry Reding 600*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0); 601*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1); 602*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2); 603*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3); 604*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4); 605*dec72739SThierry Reding 606*dec72739SThierry Reding /* start calibration */ 607*dec72739SThierry Reding tegra_dsi_pad_enable(dsi); 608*dec72739SThierry Reding 609*dec72739SThierry Reding value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | 610*dec72739SThierry Reding DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | 611*dec72739SThierry Reding DSI_PAD_OUT_CLK(0x0); 612*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); 613*dec72739SThierry Reding 614*dec72739SThierry Reding return tegra_mipi_calibrate(dsi->mipi); 615*dec72739SThierry Reding } 616*dec72739SThierry Reding 617*dec72739SThierry Reding static int tegra_dsi_init(struct host1x_client *client) 618*dec72739SThierry Reding { 619*dec72739SThierry Reding struct tegra_drm *tegra = dev_get_drvdata(client->parent); 620*dec72739SThierry Reding struct tegra_dsi *dsi = host1x_client_to_dsi(client); 621*dec72739SThierry Reding unsigned long value, i; 622*dec72739SThierry Reding int err; 623*dec72739SThierry Reding 624*dec72739SThierry Reding dsi->output.type = TEGRA_OUTPUT_DSI; 625*dec72739SThierry Reding dsi->output.dev = client->dev; 626*dec72739SThierry Reding dsi->output.ops = &dsi_ops; 627*dec72739SThierry Reding 628*dec72739SThierry Reding err = tegra_output_init(tegra->drm, &dsi->output); 629*dec72739SThierry Reding if (err < 0) { 630*dec72739SThierry Reding dev_err(client->dev, "output setup failed: %d\n", err); 631*dec72739SThierry Reding return err; 632*dec72739SThierry Reding } 633*dec72739SThierry Reding 634*dec72739SThierry Reding if (IS_ENABLED(CONFIG_DEBUG_FS)) { 635*dec72739SThierry Reding err = tegra_dsi_debugfs_init(dsi, tegra->drm->primary); 636*dec72739SThierry Reding if (err < 0) 637*dec72739SThierry Reding dev_err(dsi->dev, "debugfs setup failed: %d\n", err); 638*dec72739SThierry Reding } 639*dec72739SThierry Reding 640*dec72739SThierry Reding /* 641*dec72739SThierry Reding * enable high-speed mode, checksum generation, ECC generation and 642*dec72739SThierry Reding * disable raw mode 643*dec72739SThierry Reding */ 644*dec72739SThierry Reding value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL); 645*dec72739SThierry Reding value |= DSI_HOST_CONTROL_ECC | DSI_HOST_CONTROL_CS | 646*dec72739SThierry Reding DSI_HOST_CONTROL_HS; 647*dec72739SThierry Reding value &= ~DSI_HOST_CONTROL_RAW; 648*dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 649*dec72739SThierry Reding 650*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_SOL_DELAY); 651*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_MAX_THRESHOLD); 652*dec72739SThierry Reding 653*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_CONTROL); 654*dec72739SThierry Reding 655*dec72739SThierry Reding for (i = 0; i < 8; i++) { 656*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + i); 657*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_8 + i); 658*dec72739SThierry Reding } 659*dec72739SThierry Reding 660*dec72739SThierry Reding for (i = 0; i < 12; i++) 661*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PKT_SEQ_0_LO + i); 662*dec72739SThierry Reding 663*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_DCS_CMDS); 664*dec72739SThierry Reding 665*dec72739SThierry Reding err = tegra_dsi_pad_calibrate(dsi); 666*dec72739SThierry Reding if (err < 0) { 667*dec72739SThierry Reding dev_err(dsi->dev, "MIPI calibration failed: %d\n", err); 668*dec72739SThierry Reding return err; 669*dec72739SThierry Reding } 670*dec72739SThierry Reding 671*dec72739SThierry Reding tegra_dsi_writel(dsi, DSI_POWER_CONTROL_ENABLE, DSI_POWER_CONTROL); 672*dec72739SThierry Reding usleep_range(300, 1000); 673*dec72739SThierry Reding 674*dec72739SThierry Reding return 0; 675*dec72739SThierry Reding } 676*dec72739SThierry Reding 677*dec72739SThierry Reding static int tegra_dsi_exit(struct host1x_client *client) 678*dec72739SThierry Reding { 679*dec72739SThierry Reding struct tegra_dsi *dsi = host1x_client_to_dsi(client); 680*dec72739SThierry Reding int err; 681*dec72739SThierry Reding 682*dec72739SThierry Reding if (IS_ENABLED(CONFIG_DEBUG_FS)) { 683*dec72739SThierry Reding err = tegra_dsi_debugfs_exit(dsi); 684*dec72739SThierry Reding if (err < 0) 685*dec72739SThierry Reding dev_err(dsi->dev, "debugfs cleanup failed: %d\n", err); 686*dec72739SThierry Reding } 687*dec72739SThierry Reding 688*dec72739SThierry Reding err = tegra_output_disable(&dsi->output); 689*dec72739SThierry Reding if (err < 0) { 690*dec72739SThierry Reding dev_err(client->dev, "output failed to disable: %d\n", err); 691*dec72739SThierry Reding return err; 692*dec72739SThierry Reding } 693*dec72739SThierry Reding 694*dec72739SThierry Reding err = tegra_output_exit(&dsi->output); 695*dec72739SThierry Reding if (err < 0) { 696*dec72739SThierry Reding dev_err(client->dev, "output cleanup failed: %d\n", err); 697*dec72739SThierry Reding return err; 698*dec72739SThierry Reding } 699*dec72739SThierry Reding 700*dec72739SThierry Reding return 0; 701*dec72739SThierry Reding } 702*dec72739SThierry Reding 703*dec72739SThierry Reding static const struct host1x_client_ops dsi_client_ops = { 704*dec72739SThierry Reding .init = tegra_dsi_init, 705*dec72739SThierry Reding .exit = tegra_dsi_exit, 706*dec72739SThierry Reding }; 707*dec72739SThierry Reding 708*dec72739SThierry Reding static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi) 709*dec72739SThierry Reding { 710*dec72739SThierry Reding struct clk *parent; 711*dec72739SThierry Reding int err; 712*dec72739SThierry Reding 713*dec72739SThierry Reding parent = clk_get_parent(dsi->clk); 714*dec72739SThierry Reding if (!parent) 715*dec72739SThierry Reding return -EINVAL; 716*dec72739SThierry Reding 717*dec72739SThierry Reding err = clk_set_parent(parent, dsi->clk_parent); 718*dec72739SThierry Reding if (err < 0) 719*dec72739SThierry Reding return err; 720*dec72739SThierry Reding 721*dec72739SThierry Reding return 0; 722*dec72739SThierry Reding } 723*dec72739SThierry Reding 724*dec72739SThierry Reding static void tegra_dsi_initialize(struct tegra_dsi *dsi) 725*dec72739SThierry Reding { 726*dec72739SThierry Reding unsigned int i; 727*dec72739SThierry Reding 728*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_POWER_CONTROL); 729*dec72739SThierry Reding 730*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_INT_ENABLE); 731*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_INT_STATUS); 732*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_INT_MASK); 733*dec72739SThierry Reding 734*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_HOST_CONTROL); 735*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_CONTROL); 736*dec72739SThierry Reding 737*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_SOL_DELAY); 738*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_MAX_THRESHOLD); 739*dec72739SThierry Reding 740*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_CONTROL); 741*dec72739SThierry Reding 742*dec72739SThierry Reding for (i = 0; i < 8; i++) { 743*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + i); 744*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_8 + i); 745*dec72739SThierry Reding } 746*dec72739SThierry Reding 747*dec72739SThierry Reding for (i = 0; i < 12; i++) 748*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PKT_SEQ_0_LO + i); 749*dec72739SThierry Reding 750*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_DCS_CMDS); 751*dec72739SThierry Reding 752*dec72739SThierry Reding for (i = 0; i < 4; i++) 753*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_0_1 + i); 754*dec72739SThierry Reding 755*dec72739SThierry Reding tegra_dsi_writel(dsi, 0x00000000, DSI_PHY_TIMING_0); 756*dec72739SThierry Reding tegra_dsi_writel(dsi, 0x00000000, DSI_PHY_TIMING_1); 757*dec72739SThierry Reding tegra_dsi_writel(dsi, 0x000000ff, DSI_PHY_TIMING_2); 758*dec72739SThierry Reding tegra_dsi_writel(dsi, 0x00000000, DSI_BTA_TIMING); 759*dec72739SThierry Reding 760*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_TIMEOUT_0); 761*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_TIMEOUT_1); 762*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_TO_TALLY); 763*dec72739SThierry Reding 764*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0); 765*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_CD); 766*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CD_STATUS); 767*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_VIDEO_MODE_CONTROL); 768*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1); 769*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2); 770*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3); 771*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4); 772*dec72739SThierry Reding 773*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL); 774*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START); 775*dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE); 776*dec72739SThierry Reding } 777*dec72739SThierry Reding 778*dec72739SThierry Reding static int tegra_dsi_host_attach(struct mipi_dsi_host *host, 779*dec72739SThierry Reding struct mipi_dsi_device *device) 780*dec72739SThierry Reding { 781*dec72739SThierry Reding struct tegra_dsi *dsi = host_to_tegra(host); 782*dec72739SThierry Reding struct tegra_output *output = &dsi->output; 783*dec72739SThierry Reding 784*dec72739SThierry Reding dsi->format = device->format; 785*dec72739SThierry Reding dsi->lanes = device->lanes; 786*dec72739SThierry Reding 787*dec72739SThierry Reding output->panel = of_drm_find_panel(device->dev.of_node); 788*dec72739SThierry Reding if (output->panel) { 789*dec72739SThierry Reding if (output->connector.dev) 790*dec72739SThierry Reding drm_helper_hpd_irq_event(output->connector.dev); 791*dec72739SThierry Reding } 792*dec72739SThierry Reding 793*dec72739SThierry Reding return 0; 794*dec72739SThierry Reding } 795*dec72739SThierry Reding 796*dec72739SThierry Reding static int tegra_dsi_host_detach(struct mipi_dsi_host *host, 797*dec72739SThierry Reding struct mipi_dsi_device *device) 798*dec72739SThierry Reding { 799*dec72739SThierry Reding struct tegra_dsi *dsi = host_to_tegra(host); 800*dec72739SThierry Reding struct tegra_output *output = &dsi->output; 801*dec72739SThierry Reding 802*dec72739SThierry Reding if (output->panel && &device->dev == output->panel->dev) { 803*dec72739SThierry Reding if (output->connector.dev) 804*dec72739SThierry Reding drm_helper_hpd_irq_event(output->connector.dev); 805*dec72739SThierry Reding 806*dec72739SThierry Reding output->panel = NULL; 807*dec72739SThierry Reding } 808*dec72739SThierry Reding 809*dec72739SThierry Reding return 0; 810*dec72739SThierry Reding } 811*dec72739SThierry Reding 812*dec72739SThierry Reding static const struct mipi_dsi_host_ops tegra_dsi_host_ops = { 813*dec72739SThierry Reding .attach = tegra_dsi_host_attach, 814*dec72739SThierry Reding .detach = tegra_dsi_host_detach, 815*dec72739SThierry Reding }; 816*dec72739SThierry Reding 817*dec72739SThierry Reding static int tegra_dsi_probe(struct platform_device *pdev) 818*dec72739SThierry Reding { 819*dec72739SThierry Reding struct tegra_dsi *dsi; 820*dec72739SThierry Reding struct resource *regs; 821*dec72739SThierry Reding int err; 822*dec72739SThierry Reding 823*dec72739SThierry Reding dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); 824*dec72739SThierry Reding if (!dsi) 825*dec72739SThierry Reding return -ENOMEM; 826*dec72739SThierry Reding 827*dec72739SThierry Reding dsi->output.dev = dsi->dev = &pdev->dev; 828*dec72739SThierry Reding 829*dec72739SThierry Reding err = tegra_output_probe(&dsi->output); 830*dec72739SThierry Reding if (err < 0) 831*dec72739SThierry Reding return err; 832*dec72739SThierry Reding 833*dec72739SThierry Reding /* 834*dec72739SThierry Reding * Assume these values by default. When a DSI peripheral driver 835*dec72739SThierry Reding * attaches to the DSI host, the parameters will be taken from 836*dec72739SThierry Reding * the attached device. 837*dec72739SThierry Reding */ 838*dec72739SThierry Reding dsi->format = MIPI_DSI_FMT_RGB888; 839*dec72739SThierry Reding dsi->lanes = 4; 840*dec72739SThierry Reding 841*dec72739SThierry Reding dsi->rst = devm_reset_control_get(&pdev->dev, "dsi"); 842*dec72739SThierry Reding if (IS_ERR(dsi->rst)) 843*dec72739SThierry Reding return PTR_ERR(dsi->rst); 844*dec72739SThierry Reding 845*dec72739SThierry Reding dsi->clk = devm_clk_get(&pdev->dev, NULL); 846*dec72739SThierry Reding if (IS_ERR(dsi->clk)) { 847*dec72739SThierry Reding dev_err(&pdev->dev, "cannot get DSI clock\n"); 848*dec72739SThierry Reding return PTR_ERR(dsi->clk); 849*dec72739SThierry Reding } 850*dec72739SThierry Reding 851*dec72739SThierry Reding err = clk_prepare_enable(dsi->clk); 852*dec72739SThierry Reding if (err < 0) { 853*dec72739SThierry Reding dev_err(&pdev->dev, "cannot enable DSI clock\n"); 854*dec72739SThierry Reding return err; 855*dec72739SThierry Reding } 856*dec72739SThierry Reding 857*dec72739SThierry Reding dsi->clk_lp = devm_clk_get(&pdev->dev, "lp"); 858*dec72739SThierry Reding if (IS_ERR(dsi->clk_lp)) { 859*dec72739SThierry Reding dev_err(&pdev->dev, "cannot get low-power clock\n"); 860*dec72739SThierry Reding return PTR_ERR(dsi->clk_lp); 861*dec72739SThierry Reding } 862*dec72739SThierry Reding 863*dec72739SThierry Reding err = clk_prepare_enable(dsi->clk_lp); 864*dec72739SThierry Reding if (err < 0) { 865*dec72739SThierry Reding dev_err(&pdev->dev, "cannot enable low-power clock\n"); 866*dec72739SThierry Reding return err; 867*dec72739SThierry Reding } 868*dec72739SThierry Reding 869*dec72739SThierry Reding dsi->clk_parent = devm_clk_get(&pdev->dev, "parent"); 870*dec72739SThierry Reding if (IS_ERR(dsi->clk_parent)) { 871*dec72739SThierry Reding dev_err(&pdev->dev, "cannot get parent clock\n"); 872*dec72739SThierry Reding return PTR_ERR(dsi->clk_parent); 873*dec72739SThierry Reding } 874*dec72739SThierry Reding 875*dec72739SThierry Reding err = clk_prepare_enable(dsi->clk_parent); 876*dec72739SThierry Reding if (err < 0) { 877*dec72739SThierry Reding dev_err(&pdev->dev, "cannot enable parent clock\n"); 878*dec72739SThierry Reding return err; 879*dec72739SThierry Reding } 880*dec72739SThierry Reding 881*dec72739SThierry Reding err = tegra_dsi_setup_clocks(dsi); 882*dec72739SThierry Reding if (err < 0) { 883*dec72739SThierry Reding dev_err(&pdev->dev, "cannot setup clocks\n"); 884*dec72739SThierry Reding return err; 885*dec72739SThierry Reding } 886*dec72739SThierry Reding 887*dec72739SThierry Reding regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 888*dec72739SThierry Reding dsi->regs = devm_ioremap_resource(&pdev->dev, regs); 889*dec72739SThierry Reding if (!dsi->regs) 890*dec72739SThierry Reding return -EADDRNOTAVAIL; 891*dec72739SThierry Reding 892*dec72739SThierry Reding tegra_dsi_initialize(dsi); 893*dec72739SThierry Reding 894*dec72739SThierry Reding dsi->mipi = tegra_mipi_request(&pdev->dev); 895*dec72739SThierry Reding if (IS_ERR(dsi->mipi)) 896*dec72739SThierry Reding return PTR_ERR(dsi->mipi); 897*dec72739SThierry Reding 898*dec72739SThierry Reding dsi->host.ops = &tegra_dsi_host_ops; 899*dec72739SThierry Reding dsi->host.dev = &pdev->dev; 900*dec72739SThierry Reding 901*dec72739SThierry Reding err = mipi_dsi_host_register(&dsi->host); 902*dec72739SThierry Reding if (err < 0) { 903*dec72739SThierry Reding dev_err(&pdev->dev, "failed to register DSI host: %d\n", err); 904*dec72739SThierry Reding return err; 905*dec72739SThierry Reding } 906*dec72739SThierry Reding 907*dec72739SThierry Reding INIT_LIST_HEAD(&dsi->client.list); 908*dec72739SThierry Reding dsi->client.ops = &dsi_client_ops; 909*dec72739SThierry Reding dsi->client.dev = &pdev->dev; 910*dec72739SThierry Reding 911*dec72739SThierry Reding err = host1x_client_register(&dsi->client); 912*dec72739SThierry Reding if (err < 0) { 913*dec72739SThierry Reding dev_err(&pdev->dev, "failed to register host1x client: %d\n", 914*dec72739SThierry Reding err); 915*dec72739SThierry Reding return err; 916*dec72739SThierry Reding } 917*dec72739SThierry Reding 918*dec72739SThierry Reding platform_set_drvdata(pdev, dsi); 919*dec72739SThierry Reding 920*dec72739SThierry Reding return 0; 921*dec72739SThierry Reding } 922*dec72739SThierry Reding 923*dec72739SThierry Reding static int tegra_dsi_remove(struct platform_device *pdev) 924*dec72739SThierry Reding { 925*dec72739SThierry Reding struct tegra_dsi *dsi = platform_get_drvdata(pdev); 926*dec72739SThierry Reding int err; 927*dec72739SThierry Reding 928*dec72739SThierry Reding err = host1x_client_unregister(&dsi->client); 929*dec72739SThierry Reding if (err < 0) { 930*dec72739SThierry Reding dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", 931*dec72739SThierry Reding err); 932*dec72739SThierry Reding return err; 933*dec72739SThierry Reding } 934*dec72739SThierry Reding 935*dec72739SThierry Reding mipi_dsi_host_unregister(&dsi->host); 936*dec72739SThierry Reding tegra_mipi_free(dsi->mipi); 937*dec72739SThierry Reding 938*dec72739SThierry Reding clk_disable_unprepare(dsi->clk_parent); 939*dec72739SThierry Reding clk_disable_unprepare(dsi->clk_lp); 940*dec72739SThierry Reding clk_disable_unprepare(dsi->clk); 941*dec72739SThierry Reding 942*dec72739SThierry Reding err = tegra_output_remove(&dsi->output); 943*dec72739SThierry Reding if (err < 0) { 944*dec72739SThierry Reding dev_err(&pdev->dev, "failed to remove output: %d\n", err); 945*dec72739SThierry Reding return err; 946*dec72739SThierry Reding } 947*dec72739SThierry Reding 948*dec72739SThierry Reding return 0; 949*dec72739SThierry Reding } 950*dec72739SThierry Reding 951*dec72739SThierry Reding static const struct of_device_id tegra_dsi_of_match[] = { 952*dec72739SThierry Reding { .compatible = "nvidia,tegra114-dsi", }, 953*dec72739SThierry Reding { }, 954*dec72739SThierry Reding }; 955*dec72739SThierry Reding 956*dec72739SThierry Reding struct platform_driver tegra_dsi_driver = { 957*dec72739SThierry Reding .driver = { 958*dec72739SThierry Reding .name = "tegra-dsi", 959*dec72739SThierry Reding .of_match_table = tegra_dsi_of_match, 960*dec72739SThierry Reding }, 961*dec72739SThierry Reding .probe = tegra_dsi_probe, 962*dec72739SThierry Reding .remove = tegra_dsi_remove, 963*dec72739SThierry Reding }; 964