1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2dec72739SThierry Reding /* 3dec72739SThierry Reding * Copyright (C) 2013 NVIDIA Corporation 4dec72739SThierry Reding */ 5dec72739SThierry Reding 6dec72739SThierry Reding #include <linux/clk.h> 7dec72739SThierry Reding #include <linux/debugfs.h> 8*eb1df694SSam Ravnborg #include <linux/delay.h> 9dec72739SThierry Reding #include <linux/host1x.h> 10dec72739SThierry Reding #include <linux/module.h> 11dec72739SThierry Reding #include <linux/of.h> 12e94236cdSThierry Reding #include <linux/of_platform.h> 13dec72739SThierry Reding #include <linux/platform_device.h> 14ef8187d7SThierry Reding #include <linux/pm_runtime.h> 15*eb1df694SSam Ravnborg #include <linux/regulator/consumer.h> 16dec72739SThierry Reding #include <linux/reset.h> 17dec72739SThierry Reding 18*eb1df694SSam Ravnborg #include <video/mipi_display.h> 193b077afbSThierry Reding 204aa3df71SThierry Reding #include <drm/drm_atomic_helper.h> 21*eb1df694SSam Ravnborg #include <drm/drm_debugfs.h> 22*eb1df694SSam Ravnborg #include <drm/drm_file.h> 23dec72739SThierry Reding #include <drm/drm_mipi_dsi.h> 24dec72739SThierry Reding #include <drm/drm_panel.h> 25dec72739SThierry Reding 26dec72739SThierry Reding #include "dc.h" 27dec72739SThierry Reding #include "drm.h" 28dec72739SThierry Reding #include "dsi.h" 29dec72739SThierry Reding #include "mipi-phy.h" 3075af8fa7SThierry Reding #include "trace.h" 31dec72739SThierry Reding 32ebd14afeSThierry Reding struct tegra_dsi_state { 33ebd14afeSThierry Reding struct drm_connector_state base; 34ebd14afeSThierry Reding 35ebd14afeSThierry Reding struct mipi_dphy_timing timing; 36ebd14afeSThierry Reding unsigned long period; 37ebd14afeSThierry Reding 38ebd14afeSThierry Reding unsigned int vrefresh; 39ebd14afeSThierry Reding unsigned int lanes; 40ebd14afeSThierry Reding unsigned long pclk; 41ebd14afeSThierry Reding unsigned long bclk; 42ebd14afeSThierry Reding 43ebd14afeSThierry Reding enum tegra_dsi_format format; 44ebd14afeSThierry Reding unsigned int mul; 45ebd14afeSThierry Reding unsigned int div; 46ebd14afeSThierry Reding }; 47ebd14afeSThierry Reding 48ebd14afeSThierry Reding static inline struct tegra_dsi_state * 49ebd14afeSThierry Reding to_dsi_state(struct drm_connector_state *state) 50ebd14afeSThierry Reding { 51ebd14afeSThierry Reding return container_of(state, struct tegra_dsi_state, base); 52ebd14afeSThierry Reding } 53ebd14afeSThierry Reding 54dec72739SThierry Reding struct tegra_dsi { 55dec72739SThierry Reding struct host1x_client client; 56dec72739SThierry Reding struct tegra_output output; 57dec72739SThierry Reding struct device *dev; 58dec72739SThierry Reding 59dec72739SThierry Reding void __iomem *regs; 60dec72739SThierry Reding 61dec72739SThierry Reding struct reset_control *rst; 62dec72739SThierry Reding struct clk *clk_parent; 63dec72739SThierry Reding struct clk *clk_lp; 64dec72739SThierry Reding struct clk *clk; 65dec72739SThierry Reding 66dec72739SThierry Reding struct drm_info_list *debugfs_files; 67dec72739SThierry Reding 6817297a28SThierry Reding unsigned long flags; 69dec72739SThierry Reding enum mipi_dsi_pixel_format format; 70dec72739SThierry Reding unsigned int lanes; 71dec72739SThierry Reding 72dec72739SThierry Reding struct tegra_mipi_device *mipi; 73dec72739SThierry Reding struct mipi_dsi_host host; 743b077afbSThierry Reding 753b077afbSThierry Reding struct regulator *vdd; 76976cebc3SThierry Reding 77976cebc3SThierry Reding unsigned int video_fifo_depth; 78976cebc3SThierry Reding unsigned int host_fifo_depth; 79e94236cdSThierry Reding 80e94236cdSThierry Reding /* for ganged-mode support */ 81e94236cdSThierry Reding struct tegra_dsi *master; 82e94236cdSThierry Reding struct tegra_dsi *slave; 83dec72739SThierry Reding }; 84dec72739SThierry Reding 85dec72739SThierry Reding static inline struct tegra_dsi * 86dec72739SThierry Reding host1x_client_to_dsi(struct host1x_client *client) 87dec72739SThierry Reding { 88dec72739SThierry Reding return container_of(client, struct tegra_dsi, client); 89dec72739SThierry Reding } 90dec72739SThierry Reding 91dec72739SThierry Reding static inline struct tegra_dsi *host_to_tegra(struct mipi_dsi_host *host) 92dec72739SThierry Reding { 93dec72739SThierry Reding return container_of(host, struct tegra_dsi, host); 94dec72739SThierry Reding } 95dec72739SThierry Reding 96dec72739SThierry Reding static inline struct tegra_dsi *to_dsi(struct tegra_output *output) 97dec72739SThierry Reding { 98dec72739SThierry Reding return container_of(output, struct tegra_dsi, output); 99dec72739SThierry Reding } 100dec72739SThierry Reding 101ebd14afeSThierry Reding static struct tegra_dsi_state *tegra_dsi_get_state(struct tegra_dsi *dsi) 102ebd14afeSThierry Reding { 103ebd14afeSThierry Reding return to_dsi_state(dsi->output.connector.state); 104ebd14afeSThierry Reding } 105ebd14afeSThierry Reding 10612831076SThierry Reding static inline u32 tegra_dsi_readl(struct tegra_dsi *dsi, unsigned int offset) 107dec72739SThierry Reding { 10875af8fa7SThierry Reding u32 value = readl(dsi->regs + (offset << 2)); 10975af8fa7SThierry Reding 11075af8fa7SThierry Reding trace_dsi_readl(dsi->dev, offset, value); 11175af8fa7SThierry Reding 11275af8fa7SThierry Reding return value; 113dec72739SThierry Reding } 114dec72739SThierry Reding 1159c0b4ca1SThierry Reding static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value, 11612831076SThierry Reding unsigned int offset) 117dec72739SThierry Reding { 11875af8fa7SThierry Reding trace_dsi_writel(dsi->dev, offset, value); 11912831076SThierry Reding writel(value, dsi->regs + (offset << 2)); 120dec72739SThierry Reding } 121dec72739SThierry Reding 122a40051c0SThierry Reding #define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name } 123a40051c0SThierry Reding 124a40051c0SThierry Reding static const struct debugfs_reg32 tegra_dsi_regs[] = { 125a40051c0SThierry Reding DEBUGFS_REG32(DSI_INCR_SYNCPT), 126a40051c0SThierry Reding DEBUGFS_REG32(DSI_INCR_SYNCPT_CONTROL), 127a40051c0SThierry Reding DEBUGFS_REG32(DSI_INCR_SYNCPT_ERROR), 128a40051c0SThierry Reding DEBUGFS_REG32(DSI_CTXSW), 129a40051c0SThierry Reding DEBUGFS_REG32(DSI_RD_DATA), 130a40051c0SThierry Reding DEBUGFS_REG32(DSI_WR_DATA), 131a40051c0SThierry Reding DEBUGFS_REG32(DSI_POWER_CONTROL), 132a40051c0SThierry Reding DEBUGFS_REG32(DSI_INT_ENABLE), 133a40051c0SThierry Reding DEBUGFS_REG32(DSI_INT_STATUS), 134a40051c0SThierry Reding DEBUGFS_REG32(DSI_INT_MASK), 135a40051c0SThierry Reding DEBUGFS_REG32(DSI_HOST_CONTROL), 136a40051c0SThierry Reding DEBUGFS_REG32(DSI_CONTROL), 137a40051c0SThierry Reding DEBUGFS_REG32(DSI_SOL_DELAY), 138a40051c0SThierry Reding DEBUGFS_REG32(DSI_MAX_THRESHOLD), 139a40051c0SThierry Reding DEBUGFS_REG32(DSI_TRIGGER), 140a40051c0SThierry Reding DEBUGFS_REG32(DSI_TX_CRC), 141a40051c0SThierry Reding DEBUGFS_REG32(DSI_STATUS), 142a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_CONTROL), 143a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_0), 144a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_1), 145a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_2), 146a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_3), 147a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_4), 148a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_5), 149a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_6), 150a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_7), 151a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_0_LO), 152a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_0_HI), 153a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_1_LO), 154a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_1_HI), 155a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_2_LO), 156a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_2_HI), 157a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_3_LO), 158a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_3_HI), 159a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_4_LO), 160a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_4_HI), 161a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_5_LO), 162a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_SEQ_5_HI), 163a40051c0SThierry Reding DEBUGFS_REG32(DSI_DCS_CMDS), 164a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_LEN_0_1), 165a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_LEN_2_3), 166a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_LEN_4_5), 167a40051c0SThierry Reding DEBUGFS_REG32(DSI_PKT_LEN_6_7), 168a40051c0SThierry Reding DEBUGFS_REG32(DSI_PHY_TIMING_0), 169a40051c0SThierry Reding DEBUGFS_REG32(DSI_PHY_TIMING_1), 170a40051c0SThierry Reding DEBUGFS_REG32(DSI_PHY_TIMING_2), 171a40051c0SThierry Reding DEBUGFS_REG32(DSI_BTA_TIMING), 172a40051c0SThierry Reding DEBUGFS_REG32(DSI_TIMEOUT_0), 173a40051c0SThierry Reding DEBUGFS_REG32(DSI_TIMEOUT_1), 174a40051c0SThierry Reding DEBUGFS_REG32(DSI_TO_TALLY), 175a40051c0SThierry Reding DEBUGFS_REG32(DSI_PAD_CONTROL_0), 176a40051c0SThierry Reding DEBUGFS_REG32(DSI_PAD_CONTROL_CD), 177a40051c0SThierry Reding DEBUGFS_REG32(DSI_PAD_CD_STATUS), 178a40051c0SThierry Reding DEBUGFS_REG32(DSI_VIDEO_MODE_CONTROL), 179a40051c0SThierry Reding DEBUGFS_REG32(DSI_PAD_CONTROL_1), 180a40051c0SThierry Reding DEBUGFS_REG32(DSI_PAD_CONTROL_2), 181a40051c0SThierry Reding DEBUGFS_REG32(DSI_PAD_CONTROL_3), 182a40051c0SThierry Reding DEBUGFS_REG32(DSI_PAD_CONTROL_4), 183a40051c0SThierry Reding DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL), 184a40051c0SThierry Reding DEBUGFS_REG32(DSI_GANGED_MODE_START), 185a40051c0SThierry Reding DEBUGFS_REG32(DSI_GANGED_MODE_SIZE), 186a40051c0SThierry Reding DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT), 187a40051c0SThierry Reding DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL), 188a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8), 189a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9), 190a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10), 191a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11), 192a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12), 193a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13), 194a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14), 195a40051c0SThierry Reding DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15), 196a40051c0SThierry Reding }; 197a40051c0SThierry Reding 198dec72739SThierry Reding static int tegra_dsi_show_regs(struct seq_file *s, void *data) 199dec72739SThierry Reding { 200dec72739SThierry Reding struct drm_info_node *node = s->private; 201dec72739SThierry Reding struct tegra_dsi *dsi = node->info_ent->data; 202171e2e6dSThierry Reding struct drm_crtc *crtc = dsi->output.encoder.crtc; 203171e2e6dSThierry Reding struct drm_device *drm = node->minor->dev; 204a40051c0SThierry Reding unsigned int i; 205171e2e6dSThierry Reding int err = 0; 206171e2e6dSThierry Reding 207171e2e6dSThierry Reding drm_modeset_lock_all(drm); 208171e2e6dSThierry Reding 209171e2e6dSThierry Reding if (!crtc || !crtc->state->active) { 210171e2e6dSThierry Reding err = -EBUSY; 211171e2e6dSThierry Reding goto unlock; 212171e2e6dSThierry Reding } 213dec72739SThierry Reding 214a40051c0SThierry Reding for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs); i++) { 215a40051c0SThierry Reding unsigned int offset = tegra_dsi_regs[i].offset; 216dec72739SThierry Reding 217a40051c0SThierry Reding seq_printf(s, "%-32s %#05x %08x\n", tegra_dsi_regs[i].name, 218a40051c0SThierry Reding offset, tegra_dsi_readl(dsi, offset)); 219a40051c0SThierry Reding } 220dec72739SThierry Reding 221171e2e6dSThierry Reding unlock: 222171e2e6dSThierry Reding drm_modeset_unlock_all(drm); 223171e2e6dSThierry Reding return err; 224dec72739SThierry Reding } 225dec72739SThierry Reding 226dec72739SThierry Reding static struct drm_info_list debugfs_files[] = { 227dec72739SThierry Reding { "regs", tegra_dsi_show_regs, 0, NULL }, 228dec72739SThierry Reding }; 229dec72739SThierry Reding 230a813d704SThierry Reding static int tegra_dsi_late_register(struct drm_connector *connector) 231dec72739SThierry Reding { 232a813d704SThierry Reding struct tegra_output *output = connector_to_output(connector); 233a813d704SThierry Reding unsigned int i, count = ARRAY_SIZE(debugfs_files); 234a813d704SThierry Reding struct drm_minor *minor = connector->dev->primary; 235a813d704SThierry Reding struct dentry *root = connector->debugfs_entry; 236a813d704SThierry Reding struct tegra_dsi *dsi = to_dsi(output); 237dec72739SThierry Reding int err; 238dec72739SThierry Reding 239dec72739SThierry Reding dsi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files), 240dec72739SThierry Reding GFP_KERNEL); 241a813d704SThierry Reding if (!dsi->debugfs_files) 242a813d704SThierry Reding return -ENOMEM; 243dec72739SThierry Reding 244a813d704SThierry Reding for (i = 0; i < count; i++) 245dec72739SThierry Reding dsi->debugfs_files[i].data = dsi; 246dec72739SThierry Reding 247a813d704SThierry Reding err = drm_debugfs_create_files(dsi->debugfs_files, count, root, minor); 248dec72739SThierry Reding if (err < 0) 249dec72739SThierry Reding goto free; 250dec72739SThierry Reding 251dec72739SThierry Reding return 0; 252dec72739SThierry Reding 253dec72739SThierry Reding free: 254dec72739SThierry Reding kfree(dsi->debugfs_files); 255dec72739SThierry Reding dsi->debugfs_files = NULL; 256dec72739SThierry Reding 257dec72739SThierry Reding return err; 258dec72739SThierry Reding } 259dec72739SThierry Reding 260a813d704SThierry Reding static void tegra_dsi_early_unregister(struct drm_connector *connector) 261dec72739SThierry Reding { 262a813d704SThierry Reding struct tegra_output *output = connector_to_output(connector); 263a813d704SThierry Reding unsigned int count = ARRAY_SIZE(debugfs_files); 264a813d704SThierry Reding struct tegra_dsi *dsi = to_dsi(output); 265dec72739SThierry Reding 266a813d704SThierry Reding drm_debugfs_remove_files(dsi->debugfs_files, count, 267a813d704SThierry Reding connector->dev->primary); 268dec72739SThierry Reding kfree(dsi->debugfs_files); 269dec72739SThierry Reding dsi->debugfs_files = NULL; 270dec72739SThierry Reding } 271dec72739SThierry Reding 272dec72739SThierry Reding #define PKT_ID0(id) ((((id) & 0x3f) << 3) | (1 << 9)) 273dec72739SThierry Reding #define PKT_LEN0(len) (((len) & 0x07) << 0) 274dec72739SThierry Reding #define PKT_ID1(id) ((((id) & 0x3f) << 13) | (1 << 19)) 275dec72739SThierry Reding #define PKT_LEN1(len) (((len) & 0x07) << 10) 276dec72739SThierry Reding #define PKT_ID2(id) ((((id) & 0x3f) << 23) | (1 << 29)) 277dec72739SThierry Reding #define PKT_LEN2(len) (((len) & 0x07) << 20) 278dec72739SThierry Reding 279dec72739SThierry Reding #define PKT_LP (1 << 30) 280dec72739SThierry Reding #define NUM_PKT_SEQ 12 281dec72739SThierry Reding 28217297a28SThierry Reding /* 28317297a28SThierry Reding * non-burst mode with sync pulses 28417297a28SThierry Reding */ 28517297a28SThierry Reding static const u32 pkt_seq_video_non_burst_sync_pulses[NUM_PKT_SEQ] = { 286dec72739SThierry Reding [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) | 287dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 288dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 289dec72739SThierry Reding PKT_LP, 290dec72739SThierry Reding [ 1] = 0, 291dec72739SThierry Reding [ 2] = PKT_ID0(MIPI_DSI_V_SYNC_END) | PKT_LEN0(0) | 292dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 293dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 294dec72739SThierry Reding PKT_LP, 295dec72739SThierry Reding [ 3] = 0, 296dec72739SThierry Reding [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 297dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 298dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 299dec72739SThierry Reding PKT_LP, 300dec72739SThierry Reding [ 5] = 0, 301dec72739SThierry Reding [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 302dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 303dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0), 304dec72739SThierry Reding [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) | 305dec72739SThierry Reding PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) | 306dec72739SThierry Reding PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4), 307dec72739SThierry Reding [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 308dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 309dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 310dec72739SThierry Reding PKT_LP, 311dec72739SThierry Reding [ 9] = 0, 312dec72739SThierry Reding [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 313dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 314dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0), 315dec72739SThierry Reding [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) | 316dec72739SThierry Reding PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) | 317dec72739SThierry Reding PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4), 318dec72739SThierry Reding }; 319dec72739SThierry Reding 32017297a28SThierry Reding /* 32117297a28SThierry Reding * non-burst mode with sync events 32217297a28SThierry Reding */ 32317297a28SThierry Reding static const u32 pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = { 32417297a28SThierry Reding [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) | 32517297a28SThierry Reding PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | 32617297a28SThierry Reding PKT_LP, 32717297a28SThierry Reding [ 1] = 0, 32817297a28SThierry Reding [ 2] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 32917297a28SThierry Reding PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | 33017297a28SThierry Reding PKT_LP, 33117297a28SThierry Reding [ 3] = 0, 33217297a28SThierry Reding [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 33317297a28SThierry Reding PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | 33417297a28SThierry Reding PKT_LP, 33517297a28SThierry Reding [ 5] = 0, 33617297a28SThierry Reding [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 33717297a28SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) | 33817297a28SThierry Reding PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3), 33917297a28SThierry Reding [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4), 34017297a28SThierry Reding [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 34117297a28SThierry Reding PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | 34217297a28SThierry Reding PKT_LP, 34317297a28SThierry Reding [ 9] = 0, 34417297a28SThierry Reding [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 34517297a28SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) | 34617297a28SThierry Reding PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3), 34717297a28SThierry Reding [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4), 34817297a28SThierry Reding }; 34917297a28SThierry Reding 350337b443dSThierry Reding static const u32 pkt_seq_command_mode[NUM_PKT_SEQ] = { 351337b443dSThierry Reding [ 0] = 0, 352337b443dSThierry Reding [ 1] = 0, 353337b443dSThierry Reding [ 2] = 0, 354337b443dSThierry Reding [ 3] = 0, 355337b443dSThierry Reding [ 4] = 0, 356337b443dSThierry Reding [ 5] = 0, 357337b443dSThierry Reding [ 6] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(3) | PKT_LP, 358337b443dSThierry Reding [ 7] = 0, 359337b443dSThierry Reding [ 8] = 0, 360337b443dSThierry Reding [ 9] = 0, 361337b443dSThierry Reding [10] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(5) | PKT_LP, 362337b443dSThierry Reding [11] = 0, 363337b443dSThierry Reding }; 364337b443dSThierry Reding 365ebd14afeSThierry Reding static void tegra_dsi_set_phy_timing(struct tegra_dsi *dsi, 366ebd14afeSThierry Reding unsigned long period, 367ebd14afeSThierry Reding const struct mipi_dphy_timing *timing) 368dec72739SThierry Reding { 3699c0b4ca1SThierry Reding u32 value; 370dec72739SThierry Reding 371ebd14afeSThierry Reding value = DSI_TIMING_FIELD(timing->hsexit, period, 1) << 24 | 372ebd14afeSThierry Reding DSI_TIMING_FIELD(timing->hstrail, period, 0) << 16 | 373ebd14afeSThierry Reding DSI_TIMING_FIELD(timing->hszero, period, 3) << 8 | 374ebd14afeSThierry Reding DSI_TIMING_FIELD(timing->hsprepare, period, 1); 375dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_0); 376dec72739SThierry Reding 377ebd14afeSThierry Reding value = DSI_TIMING_FIELD(timing->clktrail, period, 1) << 24 | 378ebd14afeSThierry Reding DSI_TIMING_FIELD(timing->clkpost, period, 1) << 16 | 379ebd14afeSThierry Reding DSI_TIMING_FIELD(timing->clkzero, period, 1) << 8 | 380ebd14afeSThierry Reding DSI_TIMING_FIELD(timing->lpx, period, 1); 381dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_1); 382dec72739SThierry Reding 383ebd14afeSThierry Reding value = DSI_TIMING_FIELD(timing->clkprepare, period, 1) << 16 | 384ebd14afeSThierry Reding DSI_TIMING_FIELD(timing->clkpre, period, 1) << 8 | 385dec72739SThierry Reding DSI_TIMING_FIELD(0xff * period, period, 0) << 0; 386dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_2); 387dec72739SThierry Reding 388ebd14afeSThierry Reding value = DSI_TIMING_FIELD(timing->taget, period, 1) << 16 | 389ebd14afeSThierry Reding DSI_TIMING_FIELD(timing->tasure, period, 1) << 8 | 390ebd14afeSThierry Reding DSI_TIMING_FIELD(timing->tago, period, 1); 391dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_BTA_TIMING); 392dec72739SThierry Reding 3937e3bc3a9SSean Paul if (dsi->slave) 394ebd14afeSThierry Reding tegra_dsi_set_phy_timing(dsi->slave, period, timing); 395dec72739SThierry Reding } 396dec72739SThierry Reding 397dec72739SThierry Reding static int tegra_dsi_get_muldiv(enum mipi_dsi_pixel_format format, 398dec72739SThierry Reding unsigned int *mulp, unsigned int *divp) 399dec72739SThierry Reding { 400dec72739SThierry Reding switch (format) { 401dec72739SThierry Reding case MIPI_DSI_FMT_RGB666_PACKED: 402dec72739SThierry Reding case MIPI_DSI_FMT_RGB888: 403dec72739SThierry Reding *mulp = 3; 404dec72739SThierry Reding *divp = 1; 405dec72739SThierry Reding break; 406dec72739SThierry Reding 407dec72739SThierry Reding case MIPI_DSI_FMT_RGB565: 408dec72739SThierry Reding *mulp = 2; 409dec72739SThierry Reding *divp = 1; 410dec72739SThierry Reding break; 411dec72739SThierry Reding 412dec72739SThierry Reding case MIPI_DSI_FMT_RGB666: 413dec72739SThierry Reding *mulp = 9; 414dec72739SThierry Reding *divp = 4; 415dec72739SThierry Reding break; 416dec72739SThierry Reding 417dec72739SThierry Reding default: 418dec72739SThierry Reding return -EINVAL; 419dec72739SThierry Reding } 420dec72739SThierry Reding 421dec72739SThierry Reding return 0; 422dec72739SThierry Reding } 423dec72739SThierry Reding 424f7d6889bSThierry Reding static int tegra_dsi_get_format(enum mipi_dsi_pixel_format format, 425f7d6889bSThierry Reding enum tegra_dsi_format *fmt) 426f7d6889bSThierry Reding { 427f7d6889bSThierry Reding switch (format) { 428f7d6889bSThierry Reding case MIPI_DSI_FMT_RGB888: 429f7d6889bSThierry Reding *fmt = TEGRA_DSI_FORMAT_24P; 430f7d6889bSThierry Reding break; 431f7d6889bSThierry Reding 432f7d6889bSThierry Reding case MIPI_DSI_FMT_RGB666: 433f7d6889bSThierry Reding *fmt = TEGRA_DSI_FORMAT_18NP; 434f7d6889bSThierry Reding break; 435f7d6889bSThierry Reding 436f7d6889bSThierry Reding case MIPI_DSI_FMT_RGB666_PACKED: 437f7d6889bSThierry Reding *fmt = TEGRA_DSI_FORMAT_18P; 438f7d6889bSThierry Reding break; 439f7d6889bSThierry Reding 440f7d6889bSThierry Reding case MIPI_DSI_FMT_RGB565: 441f7d6889bSThierry Reding *fmt = TEGRA_DSI_FORMAT_16P; 442f7d6889bSThierry Reding break; 443f7d6889bSThierry Reding 444f7d6889bSThierry Reding default: 445f7d6889bSThierry Reding return -EINVAL; 446f7d6889bSThierry Reding } 447f7d6889bSThierry Reding 448f7d6889bSThierry Reding return 0; 449f7d6889bSThierry Reding } 450f7d6889bSThierry Reding 451e94236cdSThierry Reding static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start, 452e94236cdSThierry Reding unsigned int size) 453e94236cdSThierry Reding { 454e94236cdSThierry Reding u32 value; 455e94236cdSThierry Reding 456e94236cdSThierry Reding tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START); 457e94236cdSThierry Reding tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE); 458e94236cdSThierry Reding 459e94236cdSThierry Reding value = DSI_GANGED_MODE_CONTROL_ENABLE; 460e94236cdSThierry Reding tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL); 461e94236cdSThierry Reding } 462e94236cdSThierry Reding 463563eff1fSThierry Reding static void tegra_dsi_enable(struct tegra_dsi *dsi) 464dec72739SThierry Reding { 465563eff1fSThierry Reding u32 value; 466dec72739SThierry Reding 467563eff1fSThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 468563eff1fSThierry Reding value |= DSI_POWER_CONTROL_ENABLE; 469563eff1fSThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 470e94236cdSThierry Reding 471e94236cdSThierry Reding if (dsi->slave) 472e94236cdSThierry Reding tegra_dsi_enable(dsi->slave); 473e94236cdSThierry Reding } 474e94236cdSThierry Reding 475e94236cdSThierry Reding static unsigned int tegra_dsi_get_lanes(struct tegra_dsi *dsi) 476e94236cdSThierry Reding { 477e94236cdSThierry Reding if (dsi->master) 478e94236cdSThierry Reding return dsi->master->lanes + dsi->lanes; 479e94236cdSThierry Reding 480e94236cdSThierry Reding if (dsi->slave) 481e94236cdSThierry Reding return dsi->lanes + dsi->slave->lanes; 482e94236cdSThierry Reding 483e94236cdSThierry Reding return dsi->lanes; 484563eff1fSThierry Reding } 485563eff1fSThierry Reding 486ebd14afeSThierry Reding static void tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe, 487563eff1fSThierry Reding const struct drm_display_mode *mode) 488563eff1fSThierry Reding { 489563eff1fSThierry Reding unsigned int hact, hsw, hbp, hfp, i, mul, div; 490ebd14afeSThierry Reding struct tegra_dsi_state *state; 491563eff1fSThierry Reding const u32 *pkt_seq; 492563eff1fSThierry Reding u32 value; 493ebd14afeSThierry Reding 494ebd14afeSThierry Reding /* XXX: pass in state into this function? */ 495ebd14afeSThierry Reding if (dsi->master) 496ebd14afeSThierry Reding state = tegra_dsi_get_state(dsi->master); 497ebd14afeSThierry Reding else 498ebd14afeSThierry Reding state = tegra_dsi_get_state(dsi); 499ebd14afeSThierry Reding 500ebd14afeSThierry Reding mul = state->mul; 501ebd14afeSThierry Reding div = state->div; 502334ae6b5SThierry Reding 50317297a28SThierry Reding if (dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { 50417297a28SThierry Reding DRM_DEBUG_KMS("Non-burst video mode with sync pulses\n"); 50517297a28SThierry Reding pkt_seq = pkt_seq_video_non_burst_sync_pulses; 506337b443dSThierry Reding } else if (dsi->flags & MIPI_DSI_MODE_VIDEO) { 50717297a28SThierry Reding DRM_DEBUG_KMS("Non-burst video mode with sync events\n"); 50817297a28SThierry Reding pkt_seq = pkt_seq_video_non_burst_sync_events; 509337b443dSThierry Reding } else { 510337b443dSThierry Reding DRM_DEBUG_KMS("Command mode\n"); 511337b443dSThierry Reding pkt_seq = pkt_seq_command_mode; 51217297a28SThierry Reding } 51317297a28SThierry Reding 514ebd14afeSThierry Reding value = DSI_CONTROL_CHANNEL(0) | 515ebd14afeSThierry Reding DSI_CONTROL_FORMAT(state->format) | 516dec72739SThierry Reding DSI_CONTROL_LANES(dsi->lanes - 1) | 517563eff1fSThierry Reding DSI_CONTROL_SOURCE(pipe); 518dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_CONTROL); 519dec72739SThierry Reding 520976cebc3SThierry Reding tegra_dsi_writel(dsi, dsi->video_fifo_depth, DSI_MAX_THRESHOLD); 521dec72739SThierry Reding 522563eff1fSThierry Reding value = DSI_HOST_CONTROL_HS; 523dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 524dec72739SThierry Reding 525dec72739SThierry Reding value = tegra_dsi_readl(dsi, DSI_CONTROL); 526563eff1fSThierry Reding 5270c6b1e4bSAlexandre Courbot if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) 528dec72739SThierry Reding value |= DSI_CONTROL_HS_CLK_CTRL; 529563eff1fSThierry Reding 530dec72739SThierry Reding value &= ~DSI_CONTROL_TX_TRIG(3); 531337b443dSThierry Reding 532337b443dSThierry Reding /* enable DCS commands for command mode */ 533337b443dSThierry Reding if (dsi->flags & MIPI_DSI_MODE_VIDEO) 534dec72739SThierry Reding value &= ~DSI_CONTROL_DCS_ENABLE; 535337b443dSThierry Reding else 536337b443dSThierry Reding value |= DSI_CONTROL_DCS_ENABLE; 537337b443dSThierry Reding 538dec72739SThierry Reding value |= DSI_CONTROL_VIDEO_ENABLE; 539dec72739SThierry Reding value &= ~DSI_CONTROL_HOST_ENABLE; 540dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_CONTROL); 541dec72739SThierry Reding 542dec72739SThierry Reding for (i = 0; i < NUM_PKT_SEQ; i++) 543dec72739SThierry Reding tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i); 544dec72739SThierry Reding 545337b443dSThierry Reding if (dsi->flags & MIPI_DSI_MODE_VIDEO) { 546dec72739SThierry Reding /* horizontal active pixels */ 547dec72739SThierry Reding hact = mode->hdisplay * mul / div; 548dec72739SThierry Reding 549dec72739SThierry Reding /* horizontal sync width */ 550dec72739SThierry Reding hsw = (mode->hsync_end - mode->hsync_start) * mul / div; 551dec72739SThierry Reding 552dec72739SThierry Reding /* horizontal back porch */ 553dec72739SThierry Reding hbp = (mode->htotal - mode->hsync_end) * mul / div; 554b8be0bdbSThierry Reding 555b8be0bdbSThierry Reding if ((dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0) 556b8be0bdbSThierry Reding hbp += hsw; 557dec72739SThierry Reding 558dec72739SThierry Reding /* horizontal front porch */ 559dec72739SThierry Reding hfp = (mode->hsync_start - mode->hdisplay) * mul / div; 560b8be0bdbSThierry Reding 561b8be0bdbSThierry Reding /* subtract packet overhead */ 562b8be0bdbSThierry Reding hsw -= 10; 563b8be0bdbSThierry Reding hbp -= 14; 564dec72739SThierry Reding hfp -= 8; 565dec72739SThierry Reding 566dec72739SThierry Reding tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1); 567dec72739SThierry Reding tegra_dsi_writel(dsi, hact << 16 | hbp, DSI_PKT_LEN_2_3); 568dec72739SThierry Reding tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5); 569dec72739SThierry Reding tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7); 570dec72739SThierry Reding 571563eff1fSThierry Reding /* set SOL delay (for non-burst mode only) */ 572dec72739SThierry Reding tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY); 573e94236cdSThierry Reding 574e94236cdSThierry Reding /* TODO: implement ganged mode */ 575337b443dSThierry Reding } else { 576337b443dSThierry Reding u16 bytes; 577337b443dSThierry Reding 578e94236cdSThierry Reding if (dsi->master || dsi->slave) { 579e94236cdSThierry Reding /* 580e94236cdSThierry Reding * For ganged mode, assume symmetric left-right mode. 581e94236cdSThierry Reding */ 582e94236cdSThierry Reding bytes = 1 + (mode->hdisplay / 2) * mul / div; 583e94236cdSThierry Reding } else { 584337b443dSThierry Reding /* 1 byte (DCS command) + pixel data */ 585337b443dSThierry Reding bytes = 1 + mode->hdisplay * mul / div; 586e94236cdSThierry Reding } 587337b443dSThierry Reding 588337b443dSThierry Reding tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_0_1); 589337b443dSThierry Reding tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_2_3); 590337b443dSThierry Reding tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_4_5); 591337b443dSThierry Reding tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_6_7); 592337b443dSThierry Reding 593337b443dSThierry Reding value = MIPI_DCS_WRITE_MEMORY_START << 8 | 594337b443dSThierry Reding MIPI_DCS_WRITE_MEMORY_CONTINUE; 595337b443dSThierry Reding tegra_dsi_writel(dsi, value, DSI_DCS_CMDS); 596337b443dSThierry Reding 597e94236cdSThierry Reding /* set SOL delay */ 598e94236cdSThierry Reding if (dsi->master || dsi->slave) { 599e94236cdSThierry Reding unsigned long delay, bclk, bclk_ganged; 600ebd14afeSThierry Reding unsigned int lanes = state->lanes; 601e94236cdSThierry Reding 602e94236cdSThierry Reding /* SOL to valid, valid to FIFO and FIFO write delay */ 603e94236cdSThierry Reding delay = 4 + 4 + 2; 604e94236cdSThierry Reding delay = DIV_ROUND_UP(delay * mul, div * lanes); 605e94236cdSThierry Reding /* FIFO read delay */ 606e94236cdSThierry Reding delay = delay + 6; 607e94236cdSThierry Reding 608e94236cdSThierry Reding bclk = DIV_ROUND_UP(mode->htotal * mul, div * lanes); 609e94236cdSThierry Reding bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes); 610e94236cdSThierry Reding value = bclk - bclk_ganged + delay + 20; 611e94236cdSThierry Reding } else { 612e94236cdSThierry Reding /* TODO: revisit for non-ganged mode */ 613337b443dSThierry Reding value = 8 * mul / div; 614e94236cdSThierry Reding } 615337b443dSThierry Reding 616337b443dSThierry Reding tegra_dsi_writel(dsi, value, DSI_SOL_DELAY); 617337b443dSThierry Reding } 618dec72739SThierry Reding 619e94236cdSThierry Reding if (dsi->slave) { 620ebd14afeSThierry Reding tegra_dsi_configure(dsi->slave, pipe, mode); 621e94236cdSThierry Reding 622e94236cdSThierry Reding /* 623e94236cdSThierry Reding * TODO: Support modes other than symmetrical left-right 624e94236cdSThierry Reding * split. 625e94236cdSThierry Reding */ 626e94236cdSThierry Reding tegra_dsi_ganged_enable(dsi, 0, mode->hdisplay / 2); 627e94236cdSThierry Reding tegra_dsi_ganged_enable(dsi->slave, mode->hdisplay / 2, 628e94236cdSThierry Reding mode->hdisplay / 2); 629e94236cdSThierry Reding } 630563eff1fSThierry Reding } 631563eff1fSThierry Reding 632563eff1fSThierry Reding static int tegra_dsi_wait_idle(struct tegra_dsi *dsi, unsigned long timeout) 633563eff1fSThierry Reding { 634563eff1fSThierry Reding u32 value; 635563eff1fSThierry Reding 636563eff1fSThierry Reding timeout = jiffies + msecs_to_jiffies(timeout); 637563eff1fSThierry Reding 638563eff1fSThierry Reding while (time_before(jiffies, timeout)) { 639563eff1fSThierry Reding value = tegra_dsi_readl(dsi, DSI_STATUS); 640563eff1fSThierry Reding if (value & DSI_STATUS_IDLE) 641563eff1fSThierry Reding return 0; 642563eff1fSThierry Reding 643563eff1fSThierry Reding usleep_range(1000, 2000); 644563eff1fSThierry Reding } 645563eff1fSThierry Reding 646563eff1fSThierry Reding return -ETIMEDOUT; 647563eff1fSThierry Reding } 648563eff1fSThierry Reding 649563eff1fSThierry Reding static void tegra_dsi_video_disable(struct tegra_dsi *dsi) 650563eff1fSThierry Reding { 651563eff1fSThierry Reding u32 value; 652563eff1fSThierry Reding 653563eff1fSThierry Reding value = tegra_dsi_readl(dsi, DSI_CONTROL); 654563eff1fSThierry Reding value &= ~DSI_CONTROL_VIDEO_ENABLE; 655563eff1fSThierry Reding tegra_dsi_writel(dsi, value, DSI_CONTROL); 656e94236cdSThierry Reding 657e94236cdSThierry Reding if (dsi->slave) 658e94236cdSThierry Reding tegra_dsi_video_disable(dsi->slave); 659e94236cdSThierry Reding } 660e94236cdSThierry Reding 661e94236cdSThierry Reding static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi) 662e94236cdSThierry Reding { 663e94236cdSThierry Reding tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START); 664e94236cdSThierry Reding tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE); 665e94236cdSThierry Reding tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL); 666563eff1fSThierry Reding } 667563eff1fSThierry Reding 668ef8187d7SThierry Reding static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) 669ef8187d7SThierry Reding { 670ef8187d7SThierry Reding u32 value; 671ef8187d7SThierry Reding 672ef8187d7SThierry Reding value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); 673ef8187d7SThierry Reding tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0); 674ef8187d7SThierry Reding 675ef8187d7SThierry Reding return 0; 676ef8187d7SThierry Reding } 677ef8187d7SThierry Reding 678ef8187d7SThierry Reding static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) 679ef8187d7SThierry Reding { 680ef8187d7SThierry Reding u32 value; 681ef8187d7SThierry Reding 682ef8187d7SThierry Reding /* 683ef8187d7SThierry Reding * XXX Is this still needed? The module reset is deasserted right 684ef8187d7SThierry Reding * before this function is called. 685ef8187d7SThierry Reding */ 686ef8187d7SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0); 687ef8187d7SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1); 688ef8187d7SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2); 689ef8187d7SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3); 690ef8187d7SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4); 691ef8187d7SThierry Reding 692ef8187d7SThierry Reding /* start calibration */ 693ef8187d7SThierry Reding tegra_dsi_pad_enable(dsi); 694ef8187d7SThierry Reding 695ef8187d7SThierry Reding value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | 696ef8187d7SThierry Reding DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | 697ef8187d7SThierry Reding DSI_PAD_OUT_CLK(0x0); 698ef8187d7SThierry Reding tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); 699ef8187d7SThierry Reding 700ef8187d7SThierry Reding value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | 701ef8187d7SThierry Reding DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); 702ef8187d7SThierry Reding tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3); 703ef8187d7SThierry Reding 704ef8187d7SThierry Reding return tegra_mipi_calibrate(dsi->mipi); 705ef8187d7SThierry Reding } 706ef8187d7SThierry Reding 7075b901e78SThierry Reding static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk, 7085b901e78SThierry Reding unsigned int vrefresh) 7095b901e78SThierry Reding { 7105b901e78SThierry Reding unsigned int timeout; 7115b901e78SThierry Reding u32 value; 7125b901e78SThierry Reding 7135b901e78SThierry Reding /* one frame high-speed transmission timeout */ 7145b901e78SThierry Reding timeout = (bclk / vrefresh) / 512; 7155b901e78SThierry Reding value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout); 7165b901e78SThierry Reding tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0); 7175b901e78SThierry Reding 7185b901e78SThierry Reding /* 2 ms peripheral timeout for panel */ 7195b901e78SThierry Reding timeout = 2 * bclk / 512 * 1000; 7205b901e78SThierry Reding value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000); 7215b901e78SThierry Reding tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1); 7225b901e78SThierry Reding 7235b901e78SThierry Reding value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0); 7245b901e78SThierry Reding tegra_dsi_writel(dsi, value, DSI_TO_TALLY); 7255b901e78SThierry Reding 7265b901e78SThierry Reding if (dsi->slave) 7275b901e78SThierry Reding tegra_dsi_set_timeout(dsi->slave, bclk, vrefresh); 7285b901e78SThierry Reding } 7295b901e78SThierry Reding 730563eff1fSThierry Reding static void tegra_dsi_disable(struct tegra_dsi *dsi) 731563eff1fSThierry Reding { 732563eff1fSThierry Reding u32 value; 733563eff1fSThierry Reding 734e94236cdSThierry Reding if (dsi->slave) { 735e94236cdSThierry Reding tegra_dsi_ganged_disable(dsi->slave); 736e94236cdSThierry Reding tegra_dsi_ganged_disable(dsi); 737e94236cdSThierry Reding } 738e94236cdSThierry Reding 739563eff1fSThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 740563eff1fSThierry Reding value &= ~DSI_POWER_CONTROL_ENABLE; 741563eff1fSThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 742563eff1fSThierry Reding 743e94236cdSThierry Reding if (dsi->slave) 744e94236cdSThierry Reding tegra_dsi_disable(dsi->slave); 745e94236cdSThierry Reding 746563eff1fSThierry Reding usleep_range(5000, 10000); 747563eff1fSThierry Reding } 748563eff1fSThierry Reding 74992f0e073SThierry Reding static void tegra_dsi_soft_reset(struct tegra_dsi *dsi) 75092f0e073SThierry Reding { 75192f0e073SThierry Reding u32 value; 75292f0e073SThierry Reding 75392f0e073SThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 75492f0e073SThierry Reding value &= ~DSI_POWER_CONTROL_ENABLE; 75592f0e073SThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 75692f0e073SThierry Reding 75792f0e073SThierry Reding usleep_range(300, 1000); 75892f0e073SThierry Reding 75992f0e073SThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 76092f0e073SThierry Reding value |= DSI_POWER_CONTROL_ENABLE; 76192f0e073SThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 76292f0e073SThierry Reding 76392f0e073SThierry Reding usleep_range(300, 1000); 76492f0e073SThierry Reding 76592f0e073SThierry Reding value = tegra_dsi_readl(dsi, DSI_TRIGGER); 76692f0e073SThierry Reding if (value) 76792f0e073SThierry Reding tegra_dsi_writel(dsi, 0, DSI_TRIGGER); 76892f0e073SThierry Reding 76992f0e073SThierry Reding if (dsi->slave) 77092f0e073SThierry Reding tegra_dsi_soft_reset(dsi->slave); 77192f0e073SThierry Reding } 77292f0e073SThierry Reding 773ebd14afeSThierry Reding static void tegra_dsi_connector_reset(struct drm_connector *connector) 774ebd14afeSThierry Reding { 775280dc0e1SJon Hunter struct tegra_dsi_state *state = kzalloc(sizeof(*state), GFP_KERNEL); 776ebd14afeSThierry Reding 777280dc0e1SJon Hunter if (!state) 778280dc0e1SJon Hunter return; 779280dc0e1SJon Hunter 780280dc0e1SJon Hunter if (connector->state) { 781280dc0e1SJon Hunter __drm_atomic_helper_connector_destroy_state(connector->state); 782ebd14afeSThierry Reding kfree(connector->state); 7835459a2adSMaarten Lankhorst } 784280dc0e1SJon Hunter 785280dc0e1SJon Hunter __drm_atomic_helper_connector_reset(connector, &state->base); 786ebd14afeSThierry Reding } 787ebd14afeSThierry Reding 788ebd14afeSThierry Reding static struct drm_connector_state * 789ebd14afeSThierry Reding tegra_dsi_connector_duplicate_state(struct drm_connector *connector) 790ebd14afeSThierry Reding { 791ebd14afeSThierry Reding struct tegra_dsi_state *state = to_dsi_state(connector->state); 792ebd14afeSThierry Reding struct tegra_dsi_state *copy; 793ebd14afeSThierry Reding 794ebd14afeSThierry Reding copy = kmemdup(state, sizeof(*state), GFP_KERNEL); 795ebd14afeSThierry Reding if (!copy) 796ebd14afeSThierry Reding return NULL; 797ebd14afeSThierry Reding 798280dc0e1SJon Hunter __drm_atomic_helper_connector_duplicate_state(connector, 799280dc0e1SJon Hunter ©->base); 800280dc0e1SJon Hunter 801ebd14afeSThierry Reding return ©->base; 802ebd14afeSThierry Reding } 803ebd14afeSThierry Reding 8045b901e78SThierry Reding static const struct drm_connector_funcs tegra_dsi_connector_funcs = { 805ebd14afeSThierry Reding .reset = tegra_dsi_connector_reset, 8065b901e78SThierry Reding .detect = tegra_output_connector_detect, 8075b901e78SThierry Reding .fill_modes = drm_helper_probe_single_connector_modes, 8085b901e78SThierry Reding .destroy = tegra_output_connector_destroy, 809ebd14afeSThierry Reding .atomic_duplicate_state = tegra_dsi_connector_duplicate_state, 8104aa3df71SThierry Reding .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 811a813d704SThierry Reding .late_register = tegra_dsi_late_register, 812a813d704SThierry Reding .early_unregister = tegra_dsi_early_unregister, 8135b901e78SThierry Reding }; 8145b901e78SThierry Reding 8155b901e78SThierry Reding static enum drm_mode_status 8165b901e78SThierry Reding tegra_dsi_connector_mode_valid(struct drm_connector *connector, 8175b901e78SThierry Reding struct drm_display_mode *mode) 8185b901e78SThierry Reding { 8195b901e78SThierry Reding return MODE_OK; 8205b901e78SThierry Reding } 8215b901e78SThierry Reding 8225b901e78SThierry Reding static const struct drm_connector_helper_funcs tegra_dsi_connector_helper_funcs = { 8235b901e78SThierry Reding .get_modes = tegra_output_connector_get_modes, 8245b901e78SThierry Reding .mode_valid = tegra_dsi_connector_mode_valid, 8255b901e78SThierry Reding }; 8265b901e78SThierry Reding 8275b901e78SThierry Reding static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = { 8285b901e78SThierry Reding .destroy = tegra_output_encoder_destroy, 8295b901e78SThierry Reding }; 8305b901e78SThierry Reding 83187904c3eSThierry Reding static void tegra_dsi_unprepare(struct tegra_dsi *dsi) 83287904c3eSThierry Reding { 83387904c3eSThierry Reding int err; 83487904c3eSThierry Reding 83587904c3eSThierry Reding if (dsi->slave) 83687904c3eSThierry Reding tegra_dsi_unprepare(dsi->slave); 83787904c3eSThierry Reding 83887904c3eSThierry Reding err = tegra_mipi_disable(dsi->mipi); 83987904c3eSThierry Reding if (err < 0) 84087904c3eSThierry Reding dev_err(dsi->dev, "failed to disable MIPI calibration: %d\n", 84187904c3eSThierry Reding err); 84287904c3eSThierry Reding 84387904c3eSThierry Reding pm_runtime_put(dsi->dev); 84487904c3eSThierry Reding } 84587904c3eSThierry Reding 8465b901e78SThierry Reding static void tegra_dsi_encoder_disable(struct drm_encoder *encoder) 8475b901e78SThierry Reding { 8485b901e78SThierry Reding struct tegra_output *output = encoder_to_output(encoder); 8495b901e78SThierry Reding struct tegra_dc *dc = to_tegra_dc(encoder->crtc); 8505b901e78SThierry Reding struct tegra_dsi *dsi = to_dsi(output); 8515b901e78SThierry Reding u32 value; 8525b901e78SThierry Reding int err; 8535b901e78SThierry Reding 8545b901e78SThierry Reding if (output->panel) 8555b901e78SThierry Reding drm_panel_disable(output->panel); 8565b901e78SThierry Reding 8575b901e78SThierry Reding tegra_dsi_video_disable(dsi); 8585b901e78SThierry Reding 8595b901e78SThierry Reding /* 8605b901e78SThierry Reding * The following accesses registers of the display controller, so make 8615b901e78SThierry Reding * sure it's only executed when the output is attached to one. 8625b901e78SThierry Reding */ 8635b901e78SThierry Reding if (dc) { 8645b901e78SThierry Reding value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 8655b901e78SThierry Reding value &= ~DSI_ENABLE; 8665b901e78SThierry Reding tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 8675b901e78SThierry Reding 8685b901e78SThierry Reding tegra_dc_commit(dc); 8695b901e78SThierry Reding } 8705b901e78SThierry Reding 8715b901e78SThierry Reding err = tegra_dsi_wait_idle(dsi, 100); 8725b901e78SThierry Reding if (err < 0) 8735b901e78SThierry Reding dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err); 8745b901e78SThierry Reding 8755b901e78SThierry Reding tegra_dsi_soft_reset(dsi); 8765b901e78SThierry Reding 8775b901e78SThierry Reding if (output->panel) 8785b901e78SThierry Reding drm_panel_unprepare(output->panel); 8795b901e78SThierry Reding 8805b901e78SThierry Reding tegra_dsi_disable(dsi); 8815b901e78SThierry Reding 88287904c3eSThierry Reding tegra_dsi_unprepare(dsi); 88387904c3eSThierry Reding } 88487904c3eSThierry Reding 88587904c3eSThierry Reding static void tegra_dsi_prepare(struct tegra_dsi *dsi) 88687904c3eSThierry Reding { 88787904c3eSThierry Reding int err; 88887904c3eSThierry Reding 88987904c3eSThierry Reding pm_runtime_get_sync(dsi->dev); 89087904c3eSThierry Reding 89187904c3eSThierry Reding err = tegra_mipi_enable(dsi->mipi); 89287904c3eSThierry Reding if (err < 0) 89387904c3eSThierry Reding dev_err(dsi->dev, "failed to enable MIPI calibration: %d\n", 89487904c3eSThierry Reding err); 89587904c3eSThierry Reding 89687904c3eSThierry Reding err = tegra_dsi_pad_calibrate(dsi); 89787904c3eSThierry Reding if (err < 0) 89887904c3eSThierry Reding dev_err(dsi->dev, "MIPI calibration failed: %d\n", err); 89987904c3eSThierry Reding 90087904c3eSThierry Reding if (dsi->slave) 90187904c3eSThierry Reding tegra_dsi_prepare(dsi->slave); 9025b901e78SThierry Reding } 9035b901e78SThierry Reding 904171e2e6dSThierry Reding static void tegra_dsi_encoder_enable(struct drm_encoder *encoder) 905171e2e6dSThierry Reding { 906171e2e6dSThierry Reding struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; 907171e2e6dSThierry Reding struct tegra_output *output = encoder_to_output(encoder); 908171e2e6dSThierry Reding struct tegra_dc *dc = to_tegra_dc(encoder->crtc); 909171e2e6dSThierry Reding struct tegra_dsi *dsi = to_dsi(output); 910171e2e6dSThierry Reding struct tegra_dsi_state *state; 911171e2e6dSThierry Reding u32 value; 912ef8187d7SThierry Reding 91387904c3eSThierry Reding tegra_dsi_prepare(dsi); 914171e2e6dSThierry Reding 915171e2e6dSThierry Reding state = tegra_dsi_get_state(dsi); 916171e2e6dSThierry Reding 917171e2e6dSThierry Reding tegra_dsi_set_timeout(dsi, state->bclk, state->vrefresh); 918171e2e6dSThierry Reding 919171e2e6dSThierry Reding /* 920171e2e6dSThierry Reding * The D-PHY timing fields are expressed in byte-clock cycles, so 921171e2e6dSThierry Reding * multiply the period by 8. 922171e2e6dSThierry Reding */ 923171e2e6dSThierry Reding tegra_dsi_set_phy_timing(dsi, state->period * 8, &state->timing); 924171e2e6dSThierry Reding 925171e2e6dSThierry Reding if (output->panel) 926171e2e6dSThierry Reding drm_panel_prepare(output->panel); 927171e2e6dSThierry Reding 928171e2e6dSThierry Reding tegra_dsi_configure(dsi, dc->pipe, mode); 929171e2e6dSThierry Reding 930171e2e6dSThierry Reding /* enable display controller */ 931171e2e6dSThierry Reding value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 932171e2e6dSThierry Reding value |= DSI_ENABLE; 933171e2e6dSThierry Reding tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 934171e2e6dSThierry Reding 935171e2e6dSThierry Reding tegra_dc_commit(dc); 936171e2e6dSThierry Reding 937171e2e6dSThierry Reding /* enable DSI controller */ 938171e2e6dSThierry Reding tegra_dsi_enable(dsi); 939171e2e6dSThierry Reding 940171e2e6dSThierry Reding if (output->panel) 941171e2e6dSThierry Reding drm_panel_enable(output->panel); 942171e2e6dSThierry Reding } 943171e2e6dSThierry Reding 944ebd14afeSThierry Reding static int 945ebd14afeSThierry Reding tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder, 946ebd14afeSThierry Reding struct drm_crtc_state *crtc_state, 947ebd14afeSThierry Reding struct drm_connector_state *conn_state) 948ebd14afeSThierry Reding { 949ebd14afeSThierry Reding struct tegra_output *output = encoder_to_output(encoder); 950ebd14afeSThierry Reding struct tegra_dsi_state *state = to_dsi_state(conn_state); 951ebd14afeSThierry Reding struct tegra_dc *dc = to_tegra_dc(conn_state->crtc); 952ebd14afeSThierry Reding struct tegra_dsi *dsi = to_dsi(output); 953ebd14afeSThierry Reding unsigned int scdiv; 954ebd14afeSThierry Reding unsigned long plld; 955ebd14afeSThierry Reding int err; 956ebd14afeSThierry Reding 957ebd14afeSThierry Reding state->pclk = crtc_state->mode.clock * 1000; 958ebd14afeSThierry Reding 959ebd14afeSThierry Reding err = tegra_dsi_get_muldiv(dsi->format, &state->mul, &state->div); 960ebd14afeSThierry Reding if (err < 0) 961ebd14afeSThierry Reding return err; 962ebd14afeSThierry Reding 963ebd14afeSThierry Reding state->lanes = tegra_dsi_get_lanes(dsi); 964ebd14afeSThierry Reding 965ebd14afeSThierry Reding err = tegra_dsi_get_format(dsi->format, &state->format); 966ebd14afeSThierry Reding if (err < 0) 967ebd14afeSThierry Reding return err; 968ebd14afeSThierry Reding 969ebd14afeSThierry Reding state->vrefresh = drm_mode_vrefresh(&crtc_state->mode); 970ebd14afeSThierry Reding 971ebd14afeSThierry Reding /* compute byte clock */ 972ebd14afeSThierry Reding state->bclk = (state->pclk * state->mul) / (state->div * state->lanes); 973ebd14afeSThierry Reding 974ebd14afeSThierry Reding DRM_DEBUG_KMS("mul: %u, div: %u, lanes: %u\n", state->mul, state->div, 975ebd14afeSThierry Reding state->lanes); 976ebd14afeSThierry Reding DRM_DEBUG_KMS("format: %u, vrefresh: %u\n", state->format, 977ebd14afeSThierry Reding state->vrefresh); 978ebd14afeSThierry Reding DRM_DEBUG_KMS("bclk: %lu\n", state->bclk); 979ebd14afeSThierry Reding 980ebd14afeSThierry Reding /* 981ebd14afeSThierry Reding * Compute bit clock and round up to the next MHz. 982ebd14afeSThierry Reding */ 983ebd14afeSThierry Reding plld = DIV_ROUND_UP(state->bclk * 8, USEC_PER_SEC) * USEC_PER_SEC; 984ebd14afeSThierry Reding state->period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, plld); 985ebd14afeSThierry Reding 986ebd14afeSThierry Reding err = mipi_dphy_timing_get_default(&state->timing, state->period); 987ebd14afeSThierry Reding if (err < 0) 988ebd14afeSThierry Reding return err; 989ebd14afeSThierry Reding 990ebd14afeSThierry Reding err = mipi_dphy_timing_validate(&state->timing, state->period); 991ebd14afeSThierry Reding if (err < 0) { 992ebd14afeSThierry Reding dev_err(dsi->dev, "failed to validate D-PHY timing: %d\n", err); 993ebd14afeSThierry Reding return err; 994ebd14afeSThierry Reding } 995ebd14afeSThierry Reding 996ebd14afeSThierry Reding /* 997ebd14afeSThierry Reding * We divide the frequency by two here, but we make up for that by 998ebd14afeSThierry Reding * setting the shift clock divider (further below) to half of the 999ebd14afeSThierry Reding * correct value. 1000ebd14afeSThierry Reding */ 1001ebd14afeSThierry Reding plld /= 2; 1002ebd14afeSThierry Reding 1003ebd14afeSThierry Reding /* 1004ebd14afeSThierry Reding * Derive pixel clock from bit clock using the shift clock divider. 1005ebd14afeSThierry Reding * Note that this is only half of what we would expect, but we need 1006ebd14afeSThierry Reding * that to make up for the fact that we divided the bit clock by a 1007ebd14afeSThierry Reding * factor of two above. 1008ebd14afeSThierry Reding * 1009ebd14afeSThierry Reding * It's not clear exactly why this is necessary, but the display is 1010ebd14afeSThierry Reding * not working properly otherwise. Perhaps the PLLs cannot generate 1011ebd14afeSThierry Reding * frequencies sufficiently high. 1012ebd14afeSThierry Reding */ 1013ebd14afeSThierry Reding scdiv = ((8 * state->mul) / (state->div * state->lanes)) - 2; 1014ebd14afeSThierry Reding 1015ebd14afeSThierry Reding err = tegra_dc_state_setup_clock(dc, crtc_state, dsi->clk_parent, 1016ebd14afeSThierry Reding plld, scdiv); 1017ebd14afeSThierry Reding if (err < 0) { 1018ebd14afeSThierry Reding dev_err(output->dev, "failed to setup CRTC state: %d\n", err); 1019ebd14afeSThierry Reding return err; 1020ebd14afeSThierry Reding } 1021ebd14afeSThierry Reding 1022ebd14afeSThierry Reding return err; 1023ebd14afeSThierry Reding } 1024ebd14afeSThierry Reding 10255b901e78SThierry Reding static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = { 10265b901e78SThierry Reding .disable = tegra_dsi_encoder_disable, 1027171e2e6dSThierry Reding .enable = tegra_dsi_encoder_enable, 1028ebd14afeSThierry Reding .atomic_check = tegra_dsi_encoder_atomic_check, 1029dec72739SThierry Reding }; 1030dec72739SThierry Reding 1031dec72739SThierry Reding static int tegra_dsi_init(struct host1x_client *client) 1032dec72739SThierry Reding { 10339910f5c4SThierry Reding struct drm_device *drm = dev_get_drvdata(client->parent); 1034dec72739SThierry Reding struct tegra_dsi *dsi = host1x_client_to_dsi(client); 1035dec72739SThierry Reding int err; 1036dec72739SThierry Reding 1037e94236cdSThierry Reding /* Gangsters must not register their own outputs. */ 1038e94236cdSThierry Reding if (!dsi->master) { 1039dec72739SThierry Reding dsi->output.dev = client->dev; 1040dec72739SThierry Reding 10415b901e78SThierry Reding drm_connector_init(drm, &dsi->output.connector, 10425b901e78SThierry Reding &tegra_dsi_connector_funcs, 10435b901e78SThierry Reding DRM_MODE_CONNECTOR_DSI); 10445b901e78SThierry Reding drm_connector_helper_add(&dsi->output.connector, 10455b901e78SThierry Reding &tegra_dsi_connector_helper_funcs); 10465b901e78SThierry Reding dsi->output.connector.dpms = DRM_MODE_DPMS_OFF; 10475b901e78SThierry Reding 10485b901e78SThierry Reding drm_encoder_init(drm, &dsi->output.encoder, 10495b901e78SThierry Reding &tegra_dsi_encoder_funcs, 105013a3d91fSVille Syrjälä DRM_MODE_ENCODER_DSI, NULL); 10515b901e78SThierry Reding drm_encoder_helper_add(&dsi->output.encoder, 10525b901e78SThierry Reding &tegra_dsi_encoder_helper_funcs); 10535b901e78SThierry Reding 1054cde4c44dSDaniel Vetter drm_connector_attach_encoder(&dsi->output.connector, 10555b901e78SThierry Reding &dsi->output.encoder); 10565b901e78SThierry Reding drm_connector_register(&dsi->output.connector); 10575b901e78SThierry Reding 1058ea130b24SThierry Reding err = tegra_output_init(drm, &dsi->output); 1059ef8187d7SThierry Reding if (err < 0) 1060ef8187d7SThierry Reding dev_err(dsi->dev, "failed to initialize output: %d\n", 1061ea130b24SThierry Reding err); 1062ea130b24SThierry Reding 10635b901e78SThierry Reding dsi->output.encoder.possible_crtcs = 0x3; 1064e94236cdSThierry Reding } 1065dec72739SThierry Reding 1066dec72739SThierry Reding return 0; 1067dec72739SThierry Reding } 1068dec72739SThierry Reding 1069dec72739SThierry Reding static int tegra_dsi_exit(struct host1x_client *client) 1070dec72739SThierry Reding { 1071dec72739SThierry Reding struct tegra_dsi *dsi = host1x_client_to_dsi(client); 1072dec72739SThierry Reding 10735b901e78SThierry Reding tegra_output_exit(&dsi->output); 1074201106d8SThierry Reding 1075dec72739SThierry Reding return 0; 1076dec72739SThierry Reding } 1077dec72739SThierry Reding 1078dec72739SThierry Reding static const struct host1x_client_ops dsi_client_ops = { 1079dec72739SThierry Reding .init = tegra_dsi_init, 1080dec72739SThierry Reding .exit = tegra_dsi_exit, 1081dec72739SThierry Reding }; 1082dec72739SThierry Reding 1083dec72739SThierry Reding static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi) 1084dec72739SThierry Reding { 1085dec72739SThierry Reding struct clk *parent; 1086dec72739SThierry Reding int err; 1087dec72739SThierry Reding 1088dec72739SThierry Reding parent = clk_get_parent(dsi->clk); 1089dec72739SThierry Reding if (!parent) 1090dec72739SThierry Reding return -EINVAL; 1091dec72739SThierry Reding 1092dec72739SThierry Reding err = clk_set_parent(parent, dsi->clk_parent); 1093dec72739SThierry Reding if (err < 0) 1094dec72739SThierry Reding return err; 1095dec72739SThierry Reding 1096dec72739SThierry Reding return 0; 1097dec72739SThierry Reding } 1098dec72739SThierry Reding 10990fffdf6cSThierry Reding static const char * const error_report[16] = { 11000fffdf6cSThierry Reding "SoT Error", 11010fffdf6cSThierry Reding "SoT Sync Error", 11020fffdf6cSThierry Reding "EoT Sync Error", 11030fffdf6cSThierry Reding "Escape Mode Entry Command Error", 11040fffdf6cSThierry Reding "Low-Power Transmit Sync Error", 11050fffdf6cSThierry Reding "Peripheral Timeout Error", 11060fffdf6cSThierry Reding "False Control Error", 11070fffdf6cSThierry Reding "Contention Detected", 11080fffdf6cSThierry Reding "ECC Error, single-bit", 11090fffdf6cSThierry Reding "ECC Error, multi-bit", 11100fffdf6cSThierry Reding "Checksum Error", 11110fffdf6cSThierry Reding "DSI Data Type Not Recognized", 11120fffdf6cSThierry Reding "DSI VC ID Invalid", 11130fffdf6cSThierry Reding "Invalid Transmission Length", 11140fffdf6cSThierry Reding "Reserved", 11150fffdf6cSThierry Reding "DSI Protocol Violation", 11160fffdf6cSThierry Reding }; 11170fffdf6cSThierry Reding 11180fffdf6cSThierry Reding static ssize_t tegra_dsi_read_response(struct tegra_dsi *dsi, 11190fffdf6cSThierry Reding const struct mipi_dsi_msg *msg, 11200fffdf6cSThierry Reding size_t count) 11210fffdf6cSThierry Reding { 11220fffdf6cSThierry Reding u8 *rx = msg->rx_buf; 11230fffdf6cSThierry Reding unsigned int i, j, k; 11240fffdf6cSThierry Reding size_t size = 0; 11250fffdf6cSThierry Reding u16 errors; 11260fffdf6cSThierry Reding u32 value; 11270fffdf6cSThierry Reding 11280fffdf6cSThierry Reding /* read and parse packet header */ 11290fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_RD_DATA); 11300fffdf6cSThierry Reding 11310fffdf6cSThierry Reding switch (value & 0x3f) { 11320fffdf6cSThierry Reding case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: 11330fffdf6cSThierry Reding errors = (value >> 8) & 0xffff; 11340fffdf6cSThierry Reding dev_dbg(dsi->dev, "Acknowledge and error report: %04x\n", 11350fffdf6cSThierry Reding errors); 11360fffdf6cSThierry Reding for (i = 0; i < ARRAY_SIZE(error_report); i++) 11370fffdf6cSThierry Reding if (errors & BIT(i)) 11380fffdf6cSThierry Reding dev_dbg(dsi->dev, " %2u: %s\n", i, 11390fffdf6cSThierry Reding error_report[i]); 11400fffdf6cSThierry Reding break; 11410fffdf6cSThierry Reding 11420fffdf6cSThierry Reding case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: 11430fffdf6cSThierry Reding rx[0] = (value >> 8) & 0xff; 11440fffdf6cSThierry Reding size = 1; 11450fffdf6cSThierry Reding break; 11460fffdf6cSThierry Reding 11470fffdf6cSThierry Reding case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: 11480fffdf6cSThierry Reding rx[0] = (value >> 8) & 0xff; 11490fffdf6cSThierry Reding rx[1] = (value >> 16) & 0xff; 11500fffdf6cSThierry Reding size = 2; 11510fffdf6cSThierry Reding break; 11520fffdf6cSThierry Reding 11530fffdf6cSThierry Reding case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE: 11540fffdf6cSThierry Reding size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff); 11550fffdf6cSThierry Reding break; 11560fffdf6cSThierry Reding 11570fffdf6cSThierry Reding case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: 11580fffdf6cSThierry Reding size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff); 11590fffdf6cSThierry Reding break; 11600fffdf6cSThierry Reding 11610fffdf6cSThierry Reding default: 11620fffdf6cSThierry Reding dev_err(dsi->dev, "unhandled response type: %02x\n", 11630fffdf6cSThierry Reding value & 0x3f); 11640fffdf6cSThierry Reding return -EPROTO; 11650fffdf6cSThierry Reding } 11660fffdf6cSThierry Reding 11670fffdf6cSThierry Reding size = min(size, msg->rx_len); 11680fffdf6cSThierry Reding 11690fffdf6cSThierry Reding if (msg->rx_buf && size > 0) { 11700fffdf6cSThierry Reding for (i = 0, j = 0; i < count - 1; i++, j += 4) { 11710fffdf6cSThierry Reding u8 *rx = msg->rx_buf + j; 11720fffdf6cSThierry Reding 11730fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_RD_DATA); 11740fffdf6cSThierry Reding 11750fffdf6cSThierry Reding for (k = 0; k < 4 && (j + k) < msg->rx_len; k++) 11760fffdf6cSThierry Reding rx[j + k] = (value >> (k << 3)) & 0xff; 11770fffdf6cSThierry Reding } 11780fffdf6cSThierry Reding } 11790fffdf6cSThierry Reding 11800fffdf6cSThierry Reding return size; 11810fffdf6cSThierry Reding } 11820fffdf6cSThierry Reding 11830fffdf6cSThierry Reding static int tegra_dsi_transmit(struct tegra_dsi *dsi, unsigned long timeout) 11840fffdf6cSThierry Reding { 11850fffdf6cSThierry Reding tegra_dsi_writel(dsi, DSI_TRIGGER_HOST, DSI_TRIGGER); 11860fffdf6cSThierry Reding 11870fffdf6cSThierry Reding timeout = jiffies + msecs_to_jiffies(timeout); 11880fffdf6cSThierry Reding 11890fffdf6cSThierry Reding while (time_before(jiffies, timeout)) { 11900fffdf6cSThierry Reding u32 value = tegra_dsi_readl(dsi, DSI_TRIGGER); 11910fffdf6cSThierry Reding if ((value & DSI_TRIGGER_HOST) == 0) 11920fffdf6cSThierry Reding return 0; 11930fffdf6cSThierry Reding 11940fffdf6cSThierry Reding usleep_range(1000, 2000); 11950fffdf6cSThierry Reding } 11960fffdf6cSThierry Reding 11970fffdf6cSThierry Reding DRM_DEBUG_KMS("timeout waiting for transmission to complete\n"); 11980fffdf6cSThierry Reding return -ETIMEDOUT; 11990fffdf6cSThierry Reding } 12000fffdf6cSThierry Reding 12010fffdf6cSThierry Reding static int tegra_dsi_wait_for_response(struct tegra_dsi *dsi, 12020fffdf6cSThierry Reding unsigned long timeout) 12030fffdf6cSThierry Reding { 12040fffdf6cSThierry Reding timeout = jiffies + msecs_to_jiffies(250); 12050fffdf6cSThierry Reding 12060fffdf6cSThierry Reding while (time_before(jiffies, timeout)) { 12070fffdf6cSThierry Reding u32 value = tegra_dsi_readl(dsi, DSI_STATUS); 12080fffdf6cSThierry Reding u8 count = value & 0x1f; 12090fffdf6cSThierry Reding 12100fffdf6cSThierry Reding if (count > 0) 12110fffdf6cSThierry Reding return count; 12120fffdf6cSThierry Reding 12130fffdf6cSThierry Reding usleep_range(1000, 2000); 12140fffdf6cSThierry Reding } 12150fffdf6cSThierry Reding 12160fffdf6cSThierry Reding DRM_DEBUG_KMS("peripheral returned no data\n"); 12170fffdf6cSThierry Reding return -ETIMEDOUT; 12180fffdf6cSThierry Reding } 12190fffdf6cSThierry Reding 12200fffdf6cSThierry Reding static void tegra_dsi_writesl(struct tegra_dsi *dsi, unsigned long offset, 12210fffdf6cSThierry Reding const void *buffer, size_t size) 12220fffdf6cSThierry Reding { 12230fffdf6cSThierry Reding const u8 *buf = buffer; 12240fffdf6cSThierry Reding size_t i, j; 12250fffdf6cSThierry Reding u32 value; 12260fffdf6cSThierry Reding 12270fffdf6cSThierry Reding for (j = 0; j < size; j += 4) { 12280fffdf6cSThierry Reding value = 0; 12290fffdf6cSThierry Reding 12300fffdf6cSThierry Reding for (i = 0; i < 4 && j + i < size; i++) 12310fffdf6cSThierry Reding value |= buf[j + i] << (i << 3); 12320fffdf6cSThierry Reding 12330fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_WR_DATA); 12340fffdf6cSThierry Reding } 12350fffdf6cSThierry Reding } 12360fffdf6cSThierry Reding 12370fffdf6cSThierry Reding static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host, 12380fffdf6cSThierry Reding const struct mipi_dsi_msg *msg) 12390fffdf6cSThierry Reding { 12400fffdf6cSThierry Reding struct tegra_dsi *dsi = host_to_tegra(host); 12410fffdf6cSThierry Reding struct mipi_dsi_packet packet; 12420fffdf6cSThierry Reding const u8 *header; 12430fffdf6cSThierry Reding size_t count; 12440fffdf6cSThierry Reding ssize_t err; 12450fffdf6cSThierry Reding u32 value; 12460fffdf6cSThierry Reding 12470fffdf6cSThierry Reding err = mipi_dsi_create_packet(&packet, msg); 12480fffdf6cSThierry Reding if (err < 0) 12490fffdf6cSThierry Reding return err; 12500fffdf6cSThierry Reding 12510fffdf6cSThierry Reding header = packet.header; 12520fffdf6cSThierry Reding 12530fffdf6cSThierry Reding /* maximum FIFO depth is 1920 words */ 12540fffdf6cSThierry Reding if (packet.size > dsi->video_fifo_depth * 4) 12550fffdf6cSThierry Reding return -ENOSPC; 12560fffdf6cSThierry Reding 12570fffdf6cSThierry Reding /* reset underflow/overflow flags */ 12580fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_STATUS); 12590fffdf6cSThierry Reding if (value & (DSI_STATUS_UNDERFLOW | DSI_STATUS_OVERFLOW)) { 12600fffdf6cSThierry Reding value = DSI_HOST_CONTROL_FIFO_RESET; 12610fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 12620fffdf6cSThierry Reding usleep_range(10, 20); 12630fffdf6cSThierry Reding } 12640fffdf6cSThierry Reding 12650fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 12660fffdf6cSThierry Reding value |= DSI_POWER_CONTROL_ENABLE; 12670fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 12680fffdf6cSThierry Reding 12690fffdf6cSThierry Reding usleep_range(5000, 10000); 12700fffdf6cSThierry Reding 12710fffdf6cSThierry Reding value = DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | 12720fffdf6cSThierry Reding DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC; 12730fffdf6cSThierry Reding 12740fffdf6cSThierry Reding if ((msg->flags & MIPI_DSI_MSG_USE_LPM) == 0) 12750fffdf6cSThierry Reding value |= DSI_HOST_CONTROL_HS; 12760fffdf6cSThierry Reding 12770fffdf6cSThierry Reding /* 12780fffdf6cSThierry Reding * The host FIFO has a maximum of 64 words, so larger transmissions 12790fffdf6cSThierry Reding * need to use the video FIFO. 12800fffdf6cSThierry Reding */ 12810fffdf6cSThierry Reding if (packet.size > dsi->host_fifo_depth * 4) 12820fffdf6cSThierry Reding value |= DSI_HOST_CONTROL_FIFO_SEL; 12830fffdf6cSThierry Reding 12840fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 12850fffdf6cSThierry Reding 12860fffdf6cSThierry Reding /* 12870fffdf6cSThierry Reding * For reads and messages with explicitly requested ACK, generate a 12880fffdf6cSThierry Reding * BTA sequence after the transmission of the packet. 12890fffdf6cSThierry Reding */ 12900fffdf6cSThierry Reding if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) || 12910fffdf6cSThierry Reding (msg->rx_buf && msg->rx_len > 0)) { 12920fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL); 12930fffdf6cSThierry Reding value |= DSI_HOST_CONTROL_PKT_BTA; 12940fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 12950fffdf6cSThierry Reding } 12960fffdf6cSThierry Reding 12970fffdf6cSThierry Reding value = DSI_CONTROL_LANES(0) | DSI_CONTROL_HOST_ENABLE; 12980fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_CONTROL); 12990fffdf6cSThierry Reding 13000fffdf6cSThierry Reding /* write packet header, ECC is generated by hardware */ 13010fffdf6cSThierry Reding value = header[2] << 16 | header[1] << 8 | header[0]; 13020fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_WR_DATA); 13030fffdf6cSThierry Reding 13040fffdf6cSThierry Reding /* write payload (if any) */ 13050fffdf6cSThierry Reding if (packet.payload_length > 0) 13060fffdf6cSThierry Reding tegra_dsi_writesl(dsi, DSI_WR_DATA, packet.payload, 13070fffdf6cSThierry Reding packet.payload_length); 13080fffdf6cSThierry Reding 13090fffdf6cSThierry Reding err = tegra_dsi_transmit(dsi, 250); 13100fffdf6cSThierry Reding if (err < 0) 13110fffdf6cSThierry Reding return err; 13120fffdf6cSThierry Reding 13130fffdf6cSThierry Reding if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) || 13140fffdf6cSThierry Reding (msg->rx_buf && msg->rx_len > 0)) { 13150fffdf6cSThierry Reding err = tegra_dsi_wait_for_response(dsi, 250); 13160fffdf6cSThierry Reding if (err < 0) 13170fffdf6cSThierry Reding return err; 13180fffdf6cSThierry Reding 13190fffdf6cSThierry Reding count = err; 13200fffdf6cSThierry Reding 13210fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_RD_DATA); 13220fffdf6cSThierry Reding switch (value) { 13230fffdf6cSThierry Reding case 0x84: 13240fffdf6cSThierry Reding /* 13250fffdf6cSThierry Reding dev_dbg(dsi->dev, "ACK\n"); 13260fffdf6cSThierry Reding */ 13270fffdf6cSThierry Reding break; 13280fffdf6cSThierry Reding 13290fffdf6cSThierry Reding case 0x87: 13300fffdf6cSThierry Reding /* 13310fffdf6cSThierry Reding dev_dbg(dsi->dev, "ESCAPE\n"); 13320fffdf6cSThierry Reding */ 13330fffdf6cSThierry Reding break; 13340fffdf6cSThierry Reding 13350fffdf6cSThierry Reding default: 13360fffdf6cSThierry Reding dev_err(dsi->dev, "unknown status: %08x\n", value); 13370fffdf6cSThierry Reding break; 13380fffdf6cSThierry Reding } 13390fffdf6cSThierry Reding 13400fffdf6cSThierry Reding if (count > 1) { 13410fffdf6cSThierry Reding err = tegra_dsi_read_response(dsi, msg, count); 13420fffdf6cSThierry Reding if (err < 0) 13430fffdf6cSThierry Reding dev_err(dsi->dev, 13440fffdf6cSThierry Reding "failed to parse response: %zd\n", 13450fffdf6cSThierry Reding err); 13460fffdf6cSThierry Reding else { 13470fffdf6cSThierry Reding /* 13480fffdf6cSThierry Reding * For read commands, return the number of 13490fffdf6cSThierry Reding * bytes returned by the peripheral. 13500fffdf6cSThierry Reding */ 13510fffdf6cSThierry Reding count = err; 13520fffdf6cSThierry Reding } 13530fffdf6cSThierry Reding } 13540fffdf6cSThierry Reding } else { 13550fffdf6cSThierry Reding /* 13560fffdf6cSThierry Reding * For write commands, we have transmitted the 4-byte header 13570fffdf6cSThierry Reding * plus the variable-length payload. 13580fffdf6cSThierry Reding */ 13590fffdf6cSThierry Reding count = 4 + packet.payload_length; 13600fffdf6cSThierry Reding } 13610fffdf6cSThierry Reding 13620fffdf6cSThierry Reding return count; 13630fffdf6cSThierry Reding } 13640fffdf6cSThierry Reding 1365e94236cdSThierry Reding static int tegra_dsi_ganged_setup(struct tegra_dsi *dsi) 1366e94236cdSThierry Reding { 1367e94236cdSThierry Reding struct clk *parent; 1368e94236cdSThierry Reding int err; 1369e94236cdSThierry Reding 1370e94236cdSThierry Reding /* make sure both DSI controllers share the same PLL */ 1371e94236cdSThierry Reding parent = clk_get_parent(dsi->slave->clk); 1372e94236cdSThierry Reding if (!parent) 1373e94236cdSThierry Reding return -EINVAL; 1374e94236cdSThierry Reding 1375e94236cdSThierry Reding err = clk_set_parent(parent, dsi->clk_parent); 1376e94236cdSThierry Reding if (err < 0) 1377e94236cdSThierry Reding return err; 1378e94236cdSThierry Reding 1379e94236cdSThierry Reding return 0; 1380e94236cdSThierry Reding } 1381e94236cdSThierry Reding 1382dec72739SThierry Reding static int tegra_dsi_host_attach(struct mipi_dsi_host *host, 1383dec72739SThierry Reding struct mipi_dsi_device *device) 1384dec72739SThierry Reding { 1385dec72739SThierry Reding struct tegra_dsi *dsi = host_to_tegra(host); 1386dec72739SThierry Reding 138717297a28SThierry Reding dsi->flags = device->mode_flags; 1388dec72739SThierry Reding dsi->format = device->format; 1389dec72739SThierry Reding dsi->lanes = device->lanes; 1390dec72739SThierry Reding 1391e94236cdSThierry Reding if (dsi->slave) { 1392e94236cdSThierry Reding int err; 1393e94236cdSThierry Reding 1394e94236cdSThierry Reding dev_dbg(dsi->dev, "attaching dual-channel device %s\n", 1395e94236cdSThierry Reding dev_name(&device->dev)); 1396e94236cdSThierry Reding 1397e94236cdSThierry Reding err = tegra_dsi_ganged_setup(dsi); 1398e94236cdSThierry Reding if (err < 0) { 1399e94236cdSThierry Reding dev_err(dsi->dev, "failed to set up ganged mode: %d\n", 1400e94236cdSThierry Reding err); 1401e94236cdSThierry Reding return err; 1402e94236cdSThierry Reding } 1403e94236cdSThierry Reding } 1404e94236cdSThierry Reding 1405e94236cdSThierry Reding /* 1406e94236cdSThierry Reding * Slaves don't have a panel associated with them, so they provide 1407e94236cdSThierry Reding * merely the second channel. 1408e94236cdSThierry Reding */ 1409e94236cdSThierry Reding if (!dsi->master) { 1410e94236cdSThierry Reding struct tegra_output *output = &dsi->output; 1411e94236cdSThierry Reding 1412dec72739SThierry Reding output->panel = of_drm_find_panel(device->dev.of_node); 14135fa8e4a2SBoris Brezillon if (IS_ERR(output->panel)) 14145fa8e4a2SBoris Brezillon output->panel = NULL; 14155fa8e4a2SBoris Brezillon 1416e94236cdSThierry Reding if (output->panel && output->connector.dev) { 1417e94236cdSThierry Reding drm_panel_attach(output->panel, &output->connector); 1418dec72739SThierry Reding drm_helper_hpd_irq_event(output->connector.dev); 1419dec72739SThierry Reding } 1420e94236cdSThierry Reding } 1421dec72739SThierry Reding 1422dec72739SThierry Reding return 0; 1423dec72739SThierry Reding } 1424dec72739SThierry Reding 1425dec72739SThierry Reding static int tegra_dsi_host_detach(struct mipi_dsi_host *host, 1426dec72739SThierry Reding struct mipi_dsi_device *device) 1427dec72739SThierry Reding { 1428dec72739SThierry Reding struct tegra_dsi *dsi = host_to_tegra(host); 1429dec72739SThierry Reding struct tegra_output *output = &dsi->output; 1430dec72739SThierry Reding 1431dec72739SThierry Reding if (output->panel && &device->dev == output->panel->dev) { 1432ba3df979SThierry Reding output->panel = NULL; 1433ba3df979SThierry Reding 1434dec72739SThierry Reding if (output->connector.dev) 1435dec72739SThierry Reding drm_helper_hpd_irq_event(output->connector.dev); 1436dec72739SThierry Reding } 1437dec72739SThierry Reding 1438dec72739SThierry Reding return 0; 1439dec72739SThierry Reding } 1440dec72739SThierry Reding 1441dec72739SThierry Reding static const struct mipi_dsi_host_ops tegra_dsi_host_ops = { 1442dec72739SThierry Reding .attach = tegra_dsi_host_attach, 1443dec72739SThierry Reding .detach = tegra_dsi_host_detach, 14440fffdf6cSThierry Reding .transfer = tegra_dsi_host_transfer, 1445dec72739SThierry Reding }; 1446dec72739SThierry Reding 1447e94236cdSThierry Reding static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi) 1448e94236cdSThierry Reding { 1449e94236cdSThierry Reding struct device_node *np; 1450e94236cdSThierry Reding 1451e94236cdSThierry Reding np = of_parse_phandle(dsi->dev->of_node, "nvidia,ganged-mode", 0); 1452e94236cdSThierry Reding if (np) { 1453e94236cdSThierry Reding struct platform_device *gangster = of_find_device_by_node(np); 1454e94236cdSThierry Reding 1455e94236cdSThierry Reding dsi->slave = platform_get_drvdata(gangster); 1456e94236cdSThierry Reding of_node_put(np); 1457e94236cdSThierry Reding 1458e94236cdSThierry Reding if (!dsi->slave) 1459e94236cdSThierry Reding return -EPROBE_DEFER; 1460e94236cdSThierry Reding 1461e94236cdSThierry Reding dsi->slave->master = dsi; 1462e94236cdSThierry Reding } 1463e94236cdSThierry Reding 1464e94236cdSThierry Reding return 0; 1465e94236cdSThierry Reding } 1466e94236cdSThierry Reding 1467dec72739SThierry Reding static int tegra_dsi_probe(struct platform_device *pdev) 1468dec72739SThierry Reding { 1469dec72739SThierry Reding struct tegra_dsi *dsi; 1470dec72739SThierry Reding struct resource *regs; 1471dec72739SThierry Reding int err; 1472dec72739SThierry Reding 1473dec72739SThierry Reding dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); 1474dec72739SThierry Reding if (!dsi) 1475dec72739SThierry Reding return -ENOMEM; 1476dec72739SThierry Reding 1477dec72739SThierry Reding dsi->output.dev = dsi->dev = &pdev->dev; 1478976cebc3SThierry Reding dsi->video_fifo_depth = 1920; 1479976cebc3SThierry Reding dsi->host_fifo_depth = 64; 1480dec72739SThierry Reding 1481e94236cdSThierry Reding err = tegra_dsi_ganged_probe(dsi); 1482e94236cdSThierry Reding if (err < 0) 1483e94236cdSThierry Reding return err; 1484e94236cdSThierry Reding 1485dec72739SThierry Reding err = tegra_output_probe(&dsi->output); 1486dec72739SThierry Reding if (err < 0) 1487dec72739SThierry Reding return err; 1488dec72739SThierry Reding 1489ba3df979SThierry Reding dsi->output.connector.polled = DRM_CONNECTOR_POLL_HPD; 1490ba3df979SThierry Reding 1491dec72739SThierry Reding /* 1492dec72739SThierry Reding * Assume these values by default. When a DSI peripheral driver 1493dec72739SThierry Reding * attaches to the DSI host, the parameters will be taken from 1494dec72739SThierry Reding * the attached device. 1495dec72739SThierry Reding */ 149617297a28SThierry Reding dsi->flags = MIPI_DSI_MODE_VIDEO; 1497dec72739SThierry Reding dsi->format = MIPI_DSI_FMT_RGB888; 1498dec72739SThierry Reding dsi->lanes = 4; 1499dec72739SThierry Reding 150064230aa0SJon Hunter if (!pdev->dev.pm_domain) { 1501dec72739SThierry Reding dsi->rst = devm_reset_control_get(&pdev->dev, "dsi"); 1502dec72739SThierry Reding if (IS_ERR(dsi->rst)) 1503dec72739SThierry Reding return PTR_ERR(dsi->rst); 150464230aa0SJon Hunter } 1505dec72739SThierry Reding 1506dec72739SThierry Reding dsi->clk = devm_clk_get(&pdev->dev, NULL); 1507dec72739SThierry Reding if (IS_ERR(dsi->clk)) { 1508dec72739SThierry Reding dev_err(&pdev->dev, "cannot get DSI clock\n"); 1509ef8187d7SThierry Reding return PTR_ERR(dsi->clk); 1510dec72739SThierry Reding } 1511dec72739SThierry Reding 1512dec72739SThierry Reding dsi->clk_lp = devm_clk_get(&pdev->dev, "lp"); 1513dec72739SThierry Reding if (IS_ERR(dsi->clk_lp)) { 1514dec72739SThierry Reding dev_err(&pdev->dev, "cannot get low-power clock\n"); 1515ef8187d7SThierry Reding return PTR_ERR(dsi->clk_lp); 1516dec72739SThierry Reding } 1517dec72739SThierry Reding 1518dec72739SThierry Reding dsi->clk_parent = devm_clk_get(&pdev->dev, "parent"); 1519dec72739SThierry Reding if (IS_ERR(dsi->clk_parent)) { 1520dec72739SThierry Reding dev_err(&pdev->dev, "cannot get parent clock\n"); 1521ef8187d7SThierry Reding return PTR_ERR(dsi->clk_parent); 1522dec72739SThierry Reding } 1523dec72739SThierry Reding 15243b077afbSThierry Reding dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi"); 15253b077afbSThierry Reding if (IS_ERR(dsi->vdd)) { 15263b077afbSThierry Reding dev_err(&pdev->dev, "cannot get VDD supply\n"); 1527ef8187d7SThierry Reding return PTR_ERR(dsi->vdd); 15283b077afbSThierry Reding } 15293b077afbSThierry Reding 1530dec72739SThierry Reding err = tegra_dsi_setup_clocks(dsi); 1531dec72739SThierry Reding if (err < 0) { 1532dec72739SThierry Reding dev_err(&pdev->dev, "cannot setup clocks\n"); 1533ef8187d7SThierry Reding return err; 1534dec72739SThierry Reding } 1535dec72739SThierry Reding 1536dec72739SThierry Reding regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1537dec72739SThierry Reding dsi->regs = devm_ioremap_resource(&pdev->dev, regs); 1538ef8187d7SThierry Reding if (IS_ERR(dsi->regs)) 1539ef8187d7SThierry Reding return PTR_ERR(dsi->regs); 1540dec72739SThierry Reding 1541dec72739SThierry Reding dsi->mipi = tegra_mipi_request(&pdev->dev); 1542ef8187d7SThierry Reding if (IS_ERR(dsi->mipi)) 1543ef8187d7SThierry Reding return PTR_ERR(dsi->mipi); 1544dec72739SThierry Reding 1545dec72739SThierry Reding dsi->host.ops = &tegra_dsi_host_ops; 1546dec72739SThierry Reding dsi->host.dev = &pdev->dev; 1547dec72739SThierry Reding 1548dec72739SThierry Reding err = mipi_dsi_host_register(&dsi->host); 1549dec72739SThierry Reding if (err < 0) { 1550dec72739SThierry Reding dev_err(&pdev->dev, "failed to register DSI host: %d\n", err); 1551d2d0a9d2SThierry Reding goto mipi_free; 1552dec72739SThierry Reding } 1553dec72739SThierry Reding 1554ef8187d7SThierry Reding platform_set_drvdata(pdev, dsi); 1555ef8187d7SThierry Reding pm_runtime_enable(&pdev->dev); 1556ef8187d7SThierry Reding 1557dec72739SThierry Reding INIT_LIST_HEAD(&dsi->client.list); 1558dec72739SThierry Reding dsi->client.ops = &dsi_client_ops; 1559dec72739SThierry Reding dsi->client.dev = &pdev->dev; 1560dec72739SThierry Reding 1561dec72739SThierry Reding err = host1x_client_register(&dsi->client); 1562dec72739SThierry Reding if (err < 0) { 1563dec72739SThierry Reding dev_err(&pdev->dev, "failed to register host1x client: %d\n", 1564dec72739SThierry Reding err); 1565d2d0a9d2SThierry Reding goto unregister; 1566dec72739SThierry Reding } 1567dec72739SThierry Reding 1568dec72739SThierry Reding return 0; 1569d2d0a9d2SThierry Reding 1570d2d0a9d2SThierry Reding unregister: 1571d2d0a9d2SThierry Reding mipi_dsi_host_unregister(&dsi->host); 1572d2d0a9d2SThierry Reding mipi_free: 1573d2d0a9d2SThierry Reding tegra_mipi_free(dsi->mipi); 1574d2d0a9d2SThierry Reding return err; 1575dec72739SThierry Reding } 1576dec72739SThierry Reding 1577dec72739SThierry Reding static int tegra_dsi_remove(struct platform_device *pdev) 1578dec72739SThierry Reding { 1579dec72739SThierry Reding struct tegra_dsi *dsi = platform_get_drvdata(pdev); 1580dec72739SThierry Reding int err; 1581dec72739SThierry Reding 1582ef8187d7SThierry Reding pm_runtime_disable(&pdev->dev); 1583ef8187d7SThierry Reding 1584dec72739SThierry Reding err = host1x_client_unregister(&dsi->client); 1585dec72739SThierry Reding if (err < 0) { 1586dec72739SThierry Reding dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", 1587dec72739SThierry Reding err); 1588dec72739SThierry Reding return err; 1589dec72739SThierry Reding } 1590dec72739SThierry Reding 1591328ec69eSThierry Reding tegra_output_remove(&dsi->output); 15925b901e78SThierry Reding 1593dec72739SThierry Reding mipi_dsi_host_unregister(&dsi->host); 1594dec72739SThierry Reding tegra_mipi_free(dsi->mipi); 1595dec72739SThierry Reding 1596ef8187d7SThierry Reding return 0; 1597ef8187d7SThierry Reding } 1598ef8187d7SThierry Reding 1599ef8187d7SThierry Reding #ifdef CONFIG_PM 1600ef8187d7SThierry Reding static int tegra_dsi_suspend(struct device *dev) 1601ef8187d7SThierry Reding { 1602ef8187d7SThierry Reding struct tegra_dsi *dsi = dev_get_drvdata(dev); 1603ef8187d7SThierry Reding int err; 1604ef8187d7SThierry Reding 160564230aa0SJon Hunter if (dsi->rst) { 1606ef8187d7SThierry Reding err = reset_control_assert(dsi->rst); 1607ef8187d7SThierry Reding if (err < 0) { 1608ef8187d7SThierry Reding dev_err(dev, "failed to assert reset: %d\n", err); 1609ef8187d7SThierry Reding return err; 1610ef8187d7SThierry Reding } 161164230aa0SJon Hunter } 1612ef8187d7SThierry Reding 1613ef8187d7SThierry Reding usleep_range(1000, 2000); 1614ef8187d7SThierry Reding 1615dec72739SThierry Reding clk_disable_unprepare(dsi->clk_lp); 1616dec72739SThierry Reding clk_disable_unprepare(dsi->clk); 1617ef8187d7SThierry Reding 1618ef8187d7SThierry Reding regulator_disable(dsi->vdd); 1619dec72739SThierry Reding 1620dec72739SThierry Reding return 0; 1621dec72739SThierry Reding } 1622dec72739SThierry Reding 1623ef8187d7SThierry Reding static int tegra_dsi_resume(struct device *dev) 1624ef8187d7SThierry Reding { 1625ef8187d7SThierry Reding struct tegra_dsi *dsi = dev_get_drvdata(dev); 1626ef8187d7SThierry Reding int err; 1627ef8187d7SThierry Reding 1628ef8187d7SThierry Reding err = regulator_enable(dsi->vdd); 1629ef8187d7SThierry Reding if (err < 0) { 1630ef8187d7SThierry Reding dev_err(dsi->dev, "failed to enable VDD supply: %d\n", err); 1631ef8187d7SThierry Reding return err; 1632ef8187d7SThierry Reding } 1633ef8187d7SThierry Reding 1634ef8187d7SThierry Reding err = clk_prepare_enable(dsi->clk); 1635ef8187d7SThierry Reding if (err < 0) { 1636ef8187d7SThierry Reding dev_err(dev, "cannot enable DSI clock: %d\n", err); 1637ef8187d7SThierry Reding goto disable_vdd; 1638ef8187d7SThierry Reding } 1639ef8187d7SThierry Reding 1640ef8187d7SThierry Reding err = clk_prepare_enable(dsi->clk_lp); 1641ef8187d7SThierry Reding if (err < 0) { 1642ef8187d7SThierry Reding dev_err(dev, "cannot enable low-power clock: %d\n", err); 1643ef8187d7SThierry Reding goto disable_clk; 1644ef8187d7SThierry Reding } 1645ef8187d7SThierry Reding 1646ef8187d7SThierry Reding usleep_range(1000, 2000); 1647ef8187d7SThierry Reding 164864230aa0SJon Hunter if (dsi->rst) { 1649ef8187d7SThierry Reding err = reset_control_deassert(dsi->rst); 1650ef8187d7SThierry Reding if (err < 0) { 1651ef8187d7SThierry Reding dev_err(dev, "cannot assert reset: %d\n", err); 1652ef8187d7SThierry Reding goto disable_clk_lp; 1653ef8187d7SThierry Reding } 165464230aa0SJon Hunter } 1655ef8187d7SThierry Reding 1656ef8187d7SThierry Reding return 0; 1657ef8187d7SThierry Reding 1658ef8187d7SThierry Reding disable_clk_lp: 1659ef8187d7SThierry Reding clk_disable_unprepare(dsi->clk_lp); 1660ef8187d7SThierry Reding disable_clk: 1661ef8187d7SThierry Reding clk_disable_unprepare(dsi->clk); 1662ef8187d7SThierry Reding disable_vdd: 1663ef8187d7SThierry Reding regulator_disable(dsi->vdd); 1664ef8187d7SThierry Reding return err; 1665ef8187d7SThierry Reding } 1666ef8187d7SThierry Reding #endif 1667ef8187d7SThierry Reding 1668ef8187d7SThierry Reding static const struct dev_pm_ops tegra_dsi_pm_ops = { 1669ef8187d7SThierry Reding SET_RUNTIME_PM_OPS(tegra_dsi_suspend, tegra_dsi_resume, NULL) 1670ef8187d7SThierry Reding }; 1671ef8187d7SThierry Reding 1672dec72739SThierry Reding static const struct of_device_id tegra_dsi_of_match[] = { 1673ddfb406bSThierry Reding { .compatible = "nvidia,tegra210-dsi", }, 1674c06c7930SThierry Reding { .compatible = "nvidia,tegra132-dsi", }, 16757d338587SThierry Reding { .compatible = "nvidia,tegra124-dsi", }, 1676dec72739SThierry Reding { .compatible = "nvidia,tegra114-dsi", }, 1677dec72739SThierry Reding { }, 1678dec72739SThierry Reding }; 1679ef70728cSStephen Warren MODULE_DEVICE_TABLE(of, tegra_dsi_of_match); 1680dec72739SThierry Reding 1681dec72739SThierry Reding struct platform_driver tegra_dsi_driver = { 1682dec72739SThierry Reding .driver = { 1683dec72739SThierry Reding .name = "tegra-dsi", 1684dec72739SThierry Reding .of_match_table = tegra_dsi_of_match, 1685ef8187d7SThierry Reding .pm = &tegra_dsi_pm_ops, 1686dec72739SThierry Reding }, 1687dec72739SThierry Reding .probe = tegra_dsi_probe, 1688dec72739SThierry Reding .remove = tegra_dsi_remove, 1689dec72739SThierry Reding }; 1690