Lines Matching +full:mipi +full:- +full:dsi

1 // SPDX-License-Identifier: GPL-2.0+
4 * Copyright (C) 2017-2018 Bootlin
11 #include <linux/crc-ccitt.h>
14 #include <linux/phy/phy-mipi-dphy.h>
291 static void sun6i_dsi_inst_abort(struct sun6i_dsi *dsi) in sun6i_dsi_inst_abort() argument
293 regmap_update_bits(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG, in sun6i_dsi_inst_abort()
297 static void sun6i_dsi_inst_commit(struct sun6i_dsi *dsi) in sun6i_dsi_inst_commit() argument
299 regmap_update_bits(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG, in sun6i_dsi_inst_commit()
304 static int sun6i_dsi_inst_wait_for_completion(struct sun6i_dsi *dsi) in sun6i_dsi_inst_wait_for_completion() argument
308 return regmap_read_poll_timeout(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG, in sun6i_dsi_inst_wait_for_completion()
314 static void sun6i_dsi_inst_setup(struct sun6i_dsi *dsi, in sun6i_dsi_inst_setup() argument
321 regmap_write(dsi->regs, SUN6I_DSI_INST_FUNC_REG(id), in sun6i_dsi_inst_setup()
329 static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, in sun6i_dsi_inst_init() argument
332 u8 lanes_mask = GENMASK(device->lanes - 1, 0); in sun6i_dsi_inst_init()
334 sun6i_dsi_inst_setup(dsi, DSI_INST_ID_LP11, DSI_INST_MODE_STOP, in sun6i_dsi_inst_init()
337 sun6i_dsi_inst_setup(dsi, DSI_INST_ID_TBA, DSI_INST_MODE_TBA, in sun6i_dsi_inst_init()
340 sun6i_dsi_inst_setup(dsi, DSI_INST_ID_HSC, DSI_INST_MODE_HS, in sun6i_dsi_inst_init()
343 sun6i_dsi_inst_setup(dsi, DSI_INST_ID_HSD, DSI_INST_MODE_HS, in sun6i_dsi_inst_init()
346 sun6i_dsi_inst_setup(dsi, DSI_INST_ID_LPDT, DSI_INST_MODE_ESCAPE, in sun6i_dsi_inst_init()
350 sun6i_dsi_inst_setup(dsi, DSI_INST_ID_HSCEXIT, DSI_INST_MODE_HSCEXIT, in sun6i_dsi_inst_init()
353 sun6i_dsi_inst_setup(dsi, DSI_INST_ID_NOP, DSI_INST_MODE_STOP, in sun6i_dsi_inst_init()
356 sun6i_dsi_inst_setup(dsi, DSI_INST_ID_DLY, DSI_INST_MODE_NOP, in sun6i_dsi_inst_init()
359 regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_CFG_REG(0), in sun6i_dsi_inst_init()
365 static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi, in sun6i_dsi_get_video_start_delay() argument
368 u16 delay = mode->vtotal - (mode->vsync_start - mode->vdisplay) + 1; in sun6i_dsi_get_video_start_delay()
370 if (delay > mode->vtotal) in sun6i_dsi_get_video_start_delay()
371 delay = delay % mode->vtotal; in sun6i_dsi_get_video_start_delay()
376 static u16 sun6i_dsi_get_line_num(struct sun6i_dsi *dsi, in sun6i_dsi_get_line_num() argument
379 struct mipi_dsi_device *device = dsi->device; in sun6i_dsi_get_line_num()
380 unsigned int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8; in sun6i_dsi_get_line_num()
382 return mode->htotal * Bpp / device->lanes; in sun6i_dsi_get_line_num()
385 static u16 sun6i_dsi_get_drq_edge0(struct sun6i_dsi *dsi, in sun6i_dsi_get_drq_edge0() argument
391 edge0 += (mode->hdisplay + 40) * SUN6I_DSI_TCON_DIV / 8; in sun6i_dsi_get_drq_edge0()
394 return edge0 - line_num; in sun6i_dsi_get_drq_edge0()
399 static u16 sun6i_dsi_get_drq_edge1(struct sun6i_dsi *dsi, in sun6i_dsi_get_drq_edge1() argument
403 struct mipi_dsi_device *device = dsi->device; in sun6i_dsi_get_drq_edge1()
404 unsigned int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8; in sun6i_dsi_get_drq_edge1()
405 unsigned int hbp = mode->htotal - mode->hsync_end; in sun6i_dsi_get_drq_edge1()
409 edge1 += (mode->hdisplay + hbp + 20) * Bpp / device->lanes; in sun6i_dsi_get_drq_edge1()
417 static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi, in sun6i_dsi_setup_burst() argument
420 struct mipi_dsi_device *device = dsi->device; in sun6i_dsi_setup_burst()
423 if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) { in sun6i_dsi_setup_burst()
424 u16 line_num = sun6i_dsi_get_line_num(dsi, mode); in sun6i_dsi_setup_burst()
427 edge1 = sun6i_dsi_get_drq_edge1(dsi, mode, line_num); in sun6i_dsi_setup_burst()
428 edge0 = sun6i_dsi_get_drq_edge0(dsi, mode, line_num, edge1); in sun6i_dsi_setup_burst()
430 regmap_write(dsi->regs, SUN6I_DSI_BURST_DRQ_REG, in sun6i_dsi_setup_burst()
434 regmap_write(dsi->regs, SUN6I_DSI_BURST_LINE_REG, in sun6i_dsi_setup_burst()
439 } else if ((mode->hsync_start - mode->hdisplay) > 20) { in sun6i_dsi_setup_burst()
441 u16 drq = (mode->hsync_start - mode->hdisplay) - 20; in sun6i_dsi_setup_burst()
443 drq *= mipi_dsi_pixel_format_to_bpp(device->format); in sun6i_dsi_setup_burst()
450 regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG, val); in sun6i_dsi_setup_burst()
453 static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi, in sun6i_dsi_setup_inst_loop() argument
456 struct mipi_dsi_device *device = dsi->device; in sun6i_dsi_setup_inst_loop()
457 u16 delay = 50 - 1; in sun6i_dsi_setup_inst_loop()
459 if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) { in sun6i_dsi_setup_inst_loop()
460 u32 hsync_porch = (mode->htotal - mode->hdisplay) * 150; in sun6i_dsi_setup_inst_loop()
462 delay = (hsync_porch / ((mode->clock / 1000) * 8)); in sun6i_dsi_setup_inst_loop()
463 delay -= 50; in sun6i_dsi_setup_inst_loop()
466 regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_SEL_REG, in sun6i_dsi_setup_inst_loop()
470 regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(0), in sun6i_dsi_setup_inst_loop()
471 SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) | in sun6i_dsi_setup_inst_loop()
473 regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(1), in sun6i_dsi_setup_inst_loop()
474 SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) | in sun6i_dsi_setup_inst_loop()
478 static void sun6i_dsi_setup_format(struct sun6i_dsi *dsi, in sun6i_dsi_setup_format() argument
481 struct mipi_dsi_device *device = dsi->device; in sun6i_dsi_setup_format()
482 u32 val = SUN6I_DSI_PIXEL_PH_VC(device->channel); in sun6i_dsi_setup_format()
490 switch (device->format) { in sun6i_dsi_setup_format()
512 wc = mode->hdisplay * mipi_dsi_pixel_format_to_bpp(device->format) / 8; in sun6i_dsi_setup_format()
516 regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PH_REG, val); in sun6i_dsi_setup_format()
518 regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PF0_REG, in sun6i_dsi_setup_format()
521 regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PF1_REG, in sun6i_dsi_setup_format()
525 regmap_write(dsi->regs, SUN6I_DSI_PIXEL_CTL0_REG, in sun6i_dsi_setup_format()
530 static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi, in sun6i_dsi_setup_timings() argument
533 struct mipi_dsi_device *device = dsi->device; in sun6i_dsi_setup_timings()
534 unsigned int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8; in sun6i_dsi_setup_timings()
542 if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) { in sun6i_dsi_setup_timings()
543 hblk = mode->hdisplay * Bpp; in sun6i_dsi_setup_timings()
548 if (device->lanes == 4) in sun6i_dsi_setup_timings()
559 (mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD); in sun6i_dsi_setup_timings()
568 (mode->htotal - mode->hsync_end) * Bpp - HBP_PACKET_OVERHEAD); in sun6i_dsi_setup_timings()
578 (mode->hsync_start - mode->hdisplay) * Bpp - HFP_PACKET_OVERHEAD); in sun6i_dsi_setup_timings()
587 (mode->htotal - (mode->hsync_end - mode->hsync_start)) * Bpp - in sun6i_dsi_setup_timings()
605 regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, basic_ctl); in sun6i_dsi_setup_timings()
607 regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSS_REG, in sun6i_dsi_setup_timings()
609 device->channel, in sun6i_dsi_setup_timings()
612 regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSE_REG, in sun6i_dsi_setup_timings()
614 device->channel, in sun6i_dsi_setup_timings()
617 regmap_write(dsi->regs, SUN6I_DSI_SYNC_VSS_REG, in sun6i_dsi_setup_timings()
619 device->channel, in sun6i_dsi_setup_timings()
622 regmap_write(dsi->regs, SUN6I_DSI_SYNC_VSE_REG, in sun6i_dsi_setup_timings()
624 device->channel, in sun6i_dsi_setup_timings()
627 regmap_write(dsi->regs, SUN6I_DSI_BASIC_SIZE0_REG, in sun6i_dsi_setup_timings()
628 SUN6I_DSI_BASIC_SIZE0_VSA(mode->vsync_end - in sun6i_dsi_setup_timings()
629 mode->vsync_start) | in sun6i_dsi_setup_timings()
630 SUN6I_DSI_BASIC_SIZE0_VBP(mode->vtotal - in sun6i_dsi_setup_timings()
631 mode->vsync_end)); in sun6i_dsi_setup_timings()
633 regmap_write(dsi->regs, SUN6I_DSI_BASIC_SIZE1_REG, in sun6i_dsi_setup_timings()
634 SUN6I_DSI_BASIC_SIZE1_VACT(mode->vdisplay) | in sun6i_dsi_setup_timings()
635 SUN6I_DSI_BASIC_SIZE1_VT(mode->vtotal)); in sun6i_dsi_setup_timings()
638 regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA0_REG, in sun6i_dsi_setup_timings()
639 sun6i_dsi_build_blk0_pkt(device->channel, hsa)); in sun6i_dsi_setup_timings()
640 regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA1_REG, in sun6i_dsi_setup_timings()
644 regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP0_REG, in sun6i_dsi_setup_timings()
645 sun6i_dsi_build_blk0_pkt(device->channel, hbp)); in sun6i_dsi_setup_timings()
646 regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP1_REG, in sun6i_dsi_setup_timings()
650 regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP0_REG, in sun6i_dsi_setup_timings()
651 sun6i_dsi_build_blk0_pkt(device->channel, hfp)); in sun6i_dsi_setup_timings()
652 regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP1_REG, in sun6i_dsi_setup_timings()
656 regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK0_REG, in sun6i_dsi_setup_timings()
657 sun6i_dsi_build_blk0_pkt(device->channel, hblk)); in sun6i_dsi_setup_timings()
658 regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK1_REG, in sun6i_dsi_setup_timings()
662 regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK0_REG, in sun6i_dsi_setup_timings()
663 sun6i_dsi_build_blk0_pkt(device->channel, vblk)); in sun6i_dsi_setup_timings()
664 regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK1_REG, in sun6i_dsi_setup_timings()
670 static int sun6i_dsi_start(struct sun6i_dsi *dsi, in sun6i_dsi_start() argument
675 regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG, in sun6i_dsi_start()
680 regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG, in sun6i_dsi_start()
687 regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG, in sun6i_dsi_start()
692 regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG, in sun6i_dsi_start()
700 regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG, in sun6i_dsi_start()
705 sun6i_dsi_inst_abort(dsi); in sun6i_dsi_start()
706 sun6i_dsi_inst_commit(dsi); in sun6i_dsi_start()
709 regmap_write_bits(dsi->regs, in sun6i_dsi_start()
718 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; in sun6i_dsi_encoder_enable()
719 struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder); in sun6i_dsi_encoder_enable() local
720 struct mipi_dsi_device *device = dsi->device; in sun6i_dsi_encoder_enable()
726 DRM_DEBUG_DRIVER("Enabling DSI output\n"); in sun6i_dsi_encoder_enable()
728 err = regulator_enable(dsi->regulator); in sun6i_dsi_encoder_enable()
730 dev_warn(dsi->dev, "failed to enable VCC-DSI supply: %d\n", err); in sun6i_dsi_encoder_enable()
732 reset_control_deassert(dsi->reset); in sun6i_dsi_encoder_enable()
733 clk_prepare_enable(dsi->mod_clk); in sun6i_dsi_encoder_enable()
736 * Enable the DSI block. in sun6i_dsi_encoder_enable()
738 regmap_write(dsi->regs, SUN6I_DSI_CTL_REG, SUN6I_DSI_CTL_EN); in sun6i_dsi_encoder_enable()
740 regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG, in sun6i_dsi_encoder_enable()
743 regmap_write(dsi->regs, SUN6I_DSI_TRANS_START_REG, 10); in sun6i_dsi_encoder_enable()
744 regmap_write(dsi->regs, SUN6I_DSI_TRANS_ZERO_REG, 0); in sun6i_dsi_encoder_enable()
746 sun6i_dsi_inst_init(dsi, dsi->device); in sun6i_dsi_encoder_enable()
748 regmap_write(dsi->regs, SUN6I_DSI_DEBUG_DATA_REG, 0xff); in sun6i_dsi_encoder_enable()
750 delay = sun6i_dsi_get_video_start_delay(dsi, mode); in sun6i_dsi_encoder_enable()
751 regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL1_REG, in sun6i_dsi_encoder_enable()
757 sun6i_dsi_setup_burst(dsi, mode); in sun6i_dsi_encoder_enable()
758 sun6i_dsi_setup_inst_loop(dsi, mode); in sun6i_dsi_encoder_enable()
759 sun6i_dsi_setup_format(dsi, mode); in sun6i_dsi_encoder_enable()
760 sun6i_dsi_setup_timings(dsi, mode); in sun6i_dsi_encoder_enable()
762 phy_init(dsi->dphy); in sun6i_dsi_encoder_enable()
764 phy_mipi_dphy_get_default_config(mode->clock * 1000, in sun6i_dsi_encoder_enable()
765 mipi_dsi_pixel_format_to_bpp(device->format), in sun6i_dsi_encoder_enable()
766 device->lanes, cfg); in sun6i_dsi_encoder_enable()
768 phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY); in sun6i_dsi_encoder_enable()
769 phy_configure(dsi->dphy, &opts); in sun6i_dsi_encoder_enable()
770 phy_power_on(dsi->dphy); in sun6i_dsi_encoder_enable()
772 if (dsi->panel) in sun6i_dsi_encoder_enable()
773 drm_panel_prepare(dsi->panel); in sun6i_dsi_encoder_enable()
783 * I haven't seen any artifact due to that sub-optimal in sun6i_dsi_encoder_enable()
787 if (dsi->panel) in sun6i_dsi_encoder_enable()
788 drm_panel_enable(dsi->panel); in sun6i_dsi_encoder_enable()
790 sun6i_dsi_start(dsi, DSI_START_HSC); in sun6i_dsi_encoder_enable()
794 sun6i_dsi_start(dsi, DSI_START_HSD); in sun6i_dsi_encoder_enable()
799 struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder); in sun6i_dsi_encoder_disable() local
801 DRM_DEBUG_DRIVER("Disabling DSI output\n"); in sun6i_dsi_encoder_disable()
803 if (dsi->panel) { in sun6i_dsi_encoder_disable()
804 drm_panel_disable(dsi->panel); in sun6i_dsi_encoder_disable()
805 drm_panel_unprepare(dsi->panel); in sun6i_dsi_encoder_disable()
808 phy_power_off(dsi->dphy); in sun6i_dsi_encoder_disable()
809 phy_exit(dsi->dphy); in sun6i_dsi_encoder_disable()
811 clk_disable_unprepare(dsi->mod_clk); in sun6i_dsi_encoder_disable()
812 reset_control_assert(dsi->reset); in sun6i_dsi_encoder_disable()
813 regulator_disable(dsi->regulator); in sun6i_dsi_encoder_disable()
818 struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector); in sun6i_dsi_get_modes() local
820 return drm_panel_get_modes(dsi->panel, connector); in sun6i_dsi_get_modes()
830 struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector); in sun6i_dsi_connector_detect() local
832 return dsi->panel ? connector_status_connected : in sun6i_dsi_connector_detect()
850 static u32 sun6i_dsi_dcs_build_pkt_hdr(struct sun6i_dsi *dsi, in sun6i_dsi_dcs_build_pkt_hdr() argument
853 u32 pkt = msg->type; in sun6i_dsi_dcs_build_pkt_hdr()
855 if (msg->type == MIPI_DSI_DCS_LONG_WRITE) { in sun6i_dsi_dcs_build_pkt_hdr()
856 pkt |= ((msg->tx_len) & 0xffff) << 8; in sun6i_dsi_dcs_build_pkt_hdr()
857 pkt |= (((msg->tx_len) >> 8) & 0xffff) << 16; in sun6i_dsi_dcs_build_pkt_hdr()
859 pkt |= (((u8 *)msg->tx_buf)[0] << 8); in sun6i_dsi_dcs_build_pkt_hdr()
860 if (msg->tx_len > 1) in sun6i_dsi_dcs_build_pkt_hdr()
861 pkt |= (((u8 *)msg->tx_buf)[1] << 16); in sun6i_dsi_dcs_build_pkt_hdr()
869 static int sun6i_dsi_dcs_write_short(struct sun6i_dsi *dsi, in sun6i_dsi_dcs_write_short() argument
872 regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0), in sun6i_dsi_dcs_write_short()
873 sun6i_dsi_dcs_build_pkt_hdr(dsi, msg)); in sun6i_dsi_dcs_write_short()
874 regmap_write_bits(dsi->regs, SUN6I_DSI_CMD_CTL_REG, in sun6i_dsi_dcs_write_short()
875 0xff, (4 - 1)); in sun6i_dsi_dcs_write_short()
877 sun6i_dsi_start(dsi, DSI_START_LPTX); in sun6i_dsi_dcs_write_short()
879 return msg->tx_len; in sun6i_dsi_dcs_write_short()
882 static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi, in sun6i_dsi_dcs_write_long() argument
889 regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0), in sun6i_dsi_dcs_write_long()
890 sun6i_dsi_dcs_build_pkt_hdr(dsi, msg)); in sun6i_dsi_dcs_write_long()
892 bounce = kzalloc(ALIGN(msg->tx_len + sizeof(crc), 4), GFP_KERNEL); in sun6i_dsi_dcs_write_long()
894 return -ENOMEM; in sun6i_dsi_dcs_write_long()
896 memcpy(bounce, msg->tx_buf, msg->tx_len); in sun6i_dsi_dcs_write_long()
897 len += msg->tx_len; in sun6i_dsi_dcs_write_long()
899 crc = sun6i_dsi_crc_compute(bounce, msg->tx_len); in sun6i_dsi_dcs_write_long()
900 memcpy((u8 *)bounce + msg->tx_len, &crc, sizeof(crc)); in sun6i_dsi_dcs_write_long()
903 regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, DIV_ROUND_UP(len, 4)); in sun6i_dsi_dcs_write_long()
904 regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, len + 4 - 1); in sun6i_dsi_dcs_write_long()
907 sun6i_dsi_start(dsi, DSI_START_LPTX); in sun6i_dsi_dcs_write_long()
909 ret = sun6i_dsi_inst_wait_for_completion(dsi); in sun6i_dsi_dcs_write_long()
911 sun6i_dsi_inst_abort(dsi); in sun6i_dsi_dcs_write_long()
920 return msg->tx_len; in sun6i_dsi_dcs_write_long()
923 static int sun6i_dsi_dcs_read(struct sun6i_dsi *dsi, in sun6i_dsi_dcs_read() argument
930 regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0), in sun6i_dsi_dcs_read()
931 sun6i_dsi_dcs_build_pkt_hdr(dsi, msg)); in sun6i_dsi_dcs_read()
932 regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, in sun6i_dsi_dcs_read()
933 (4 - 1)); in sun6i_dsi_dcs_read()
935 sun6i_dsi_start(dsi, DSI_START_LPRX); in sun6i_dsi_dcs_read()
937 ret = sun6i_dsi_inst_wait_for_completion(dsi); in sun6i_dsi_dcs_read()
939 sun6i_dsi_inst_abort(dsi); in sun6i_dsi_dcs_read()
948 regmap_read(dsi->regs, SUN6I_DSI_CMD_CTL_REG, &val); in sun6i_dsi_dcs_read()
950 return -EIO; in sun6i_dsi_dcs_read()
952 regmap_read(dsi->regs, SUN6I_DSI_CMD_RX_REG(0), &val); in sun6i_dsi_dcs_read()
955 return -EIO; in sun6i_dsi_dcs_read()
957 ((u8 *)msg->rx_buf)[0] = (val >> 8); in sun6i_dsi_dcs_read()
965 struct sun6i_dsi *dsi = host_to_sun6i_dsi(host); in sun6i_dsi_attach() local
966 struct drm_panel *panel = of_drm_find_panel(device->dev.of_node); in sun6i_dsi_attach()
970 if (!dsi->drm || !dsi->drm->registered) in sun6i_dsi_attach()
971 return -EPROBE_DEFER; in sun6i_dsi_attach()
973 dsi->panel = panel; in sun6i_dsi_attach()
974 dsi->device = device; in sun6i_dsi_attach()
976 drm_kms_helper_hotplug_event(dsi->drm); in sun6i_dsi_attach()
978 dev_info(host->dev, "Attached device %s\n", device->name); in sun6i_dsi_attach()
986 struct sun6i_dsi *dsi = host_to_sun6i_dsi(host); in sun6i_dsi_detach() local
988 dsi->panel = NULL; in sun6i_dsi_detach()
989 dsi->device = NULL; in sun6i_dsi_detach()
991 drm_kms_helper_hotplug_event(dsi->drm); in sun6i_dsi_detach()
999 struct sun6i_dsi *dsi = host_to_sun6i_dsi(host); in sun6i_dsi_transfer() local
1002 ret = sun6i_dsi_inst_wait_for_completion(dsi); in sun6i_dsi_transfer()
1004 sun6i_dsi_inst_abort(dsi); in sun6i_dsi_transfer()
1006 regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, in sun6i_dsi_transfer()
1011 switch (msg->type) { in sun6i_dsi_transfer()
1015 ret = sun6i_dsi_dcs_write_short(dsi, msg); in sun6i_dsi_transfer()
1019 ret = sun6i_dsi_dcs_write_long(dsi, msg); in sun6i_dsi_transfer()
1023 if (msg->rx_len == 1) { in sun6i_dsi_transfer()
1024 ret = sun6i_dsi_dcs_read(dsi, msg); in sun6i_dsi_transfer()
1030 ret = -EINVAL; in sun6i_dsi_transfer()
1047 .name = "mipi-dsi",
1054 struct sun6i_dsi *dsi = dev_get_drvdata(dev); in sun6i_dsi_bind() local
1057 drm_encoder_helper_add(&dsi->encoder, in sun6i_dsi_bind()
1059 ret = drm_simple_encoder_init(drm, &dsi->encoder, in sun6i_dsi_bind()
1062 dev_err(dsi->dev, "Couldn't initialise the DSI encoder\n"); in sun6i_dsi_bind()
1065 dsi->encoder.possible_crtcs = BIT(0); in sun6i_dsi_bind()
1067 drm_connector_helper_add(&dsi->connector, in sun6i_dsi_bind()
1069 ret = drm_connector_init(drm, &dsi->connector, in sun6i_dsi_bind()
1073 dev_err(dsi->dev, in sun6i_dsi_bind()
1074 "Couldn't initialise the DSI connector\n"); in sun6i_dsi_bind()
1078 drm_connector_attach_encoder(&dsi->connector, &dsi->encoder); in sun6i_dsi_bind()
1080 dsi->drm = drm; in sun6i_dsi_bind()
1085 drm_encoder_cleanup(&dsi->encoder); in sun6i_dsi_bind()
1092 struct sun6i_dsi *dsi = dev_get_drvdata(dev); in sun6i_dsi_unbind() local
1094 dsi->drm = NULL; in sun6i_dsi_unbind()
1104 struct device *dev = &pdev->dev; in sun6i_dsi_probe()
1106 struct sun6i_dsi *dsi; in sun6i_dsi_probe() local
1111 dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); in sun6i_dsi_probe()
1112 if (!dsi) in sun6i_dsi_probe()
1113 return -ENOMEM; in sun6i_dsi_probe()
1114 dev_set_drvdata(dev, dsi); in sun6i_dsi_probe()
1115 dsi->dev = dev; in sun6i_dsi_probe()
1116 dsi->host.ops = &sun6i_dsi_host_ops; in sun6i_dsi_probe()
1117 dsi->host.dev = dev; in sun6i_dsi_probe()
1119 if (of_device_is_compatible(dev->of_node, in sun6i_dsi_probe()
1120 "allwinner,sun6i-a31-mipi-dsi")) in sun6i_dsi_probe()
1126 dev_err(dev, "Couldn't map the DSI encoder registers\n"); in sun6i_dsi_probe()
1130 dsi->regulator = devm_regulator_get(dev, "vcc-dsi"); in sun6i_dsi_probe()
1131 if (IS_ERR(dsi->regulator)) { in sun6i_dsi_probe()
1132 dev_err(dev, "Couldn't get VCC-DSI supply\n"); in sun6i_dsi_probe()
1133 return PTR_ERR(dsi->regulator); in sun6i_dsi_probe()
1136 dsi->reset = devm_reset_control_get_shared(dev, NULL); in sun6i_dsi_probe()
1137 if (IS_ERR(dsi->reset)) { in sun6i_dsi_probe()
1139 return PTR_ERR(dsi->reset); in sun6i_dsi_probe()
1142 dsi->regs = devm_regmap_init_mmio(dev, base, &sun6i_dsi_regmap_config); in sun6i_dsi_probe()
1143 if (IS_ERR(dsi->regs)) { in sun6i_dsi_probe()
1145 return PTR_ERR(dsi->regs); in sun6i_dsi_probe()
1148 dsi->bus_clk = devm_clk_get(dev, bus_clk_name); in sun6i_dsi_probe()
1149 if (IS_ERR(dsi->bus_clk)) { in sun6i_dsi_probe()
1150 dev_err(dev, "Couldn't get the DSI bus clock\n"); in sun6i_dsi_probe()
1151 return PTR_ERR(dsi->bus_clk); in sun6i_dsi_probe()
1154 ret = regmap_mmio_attach_clk(dsi->regs, dsi->bus_clk); in sun6i_dsi_probe()
1158 if (of_device_is_compatible(dev->of_node, in sun6i_dsi_probe()
1159 "allwinner,sun6i-a31-mipi-dsi")) { in sun6i_dsi_probe()
1160 dsi->mod_clk = devm_clk_get(dev, "mod"); in sun6i_dsi_probe()
1161 if (IS_ERR(dsi->mod_clk)) { in sun6i_dsi_probe()
1162 dev_err(dev, "Couldn't get the DSI mod clock\n"); in sun6i_dsi_probe()
1163 ret = PTR_ERR(dsi->mod_clk); in sun6i_dsi_probe()
1172 clk_set_rate_exclusive(dsi->mod_clk, 297000000); in sun6i_dsi_probe()
1174 dsi->dphy = devm_phy_get(dev, "dphy"); in sun6i_dsi_probe()
1175 if (IS_ERR(dsi->dphy)) { in sun6i_dsi_probe()
1176 dev_err(dev, "Couldn't get the MIPI D-PHY\n"); in sun6i_dsi_probe()
1177 ret = PTR_ERR(dsi->dphy); in sun6i_dsi_probe()
1181 ret = mipi_dsi_host_register(&dsi->host); in sun6i_dsi_probe()
1183 dev_err(dev, "Couldn't register MIPI-DSI host\n"); in sun6i_dsi_probe()
1187 ret = component_add(&pdev->dev, &sun6i_dsi_ops); in sun6i_dsi_probe()
1196 mipi_dsi_host_unregister(&dsi->host); in sun6i_dsi_probe()
1198 clk_rate_exclusive_put(dsi->mod_clk); in sun6i_dsi_probe()
1200 if (!IS_ERR(dsi->bus_clk)) in sun6i_dsi_probe()
1201 regmap_mmio_detach_clk(dsi->regs); in sun6i_dsi_probe()
1207 struct device *dev = &pdev->dev; in sun6i_dsi_remove()
1208 struct sun6i_dsi *dsi = dev_get_drvdata(dev); in sun6i_dsi_remove() local
1210 component_del(&pdev->dev, &sun6i_dsi_ops); in sun6i_dsi_remove()
1211 mipi_dsi_host_unregister(&dsi->host); in sun6i_dsi_remove()
1212 clk_rate_exclusive_put(dsi->mod_clk); in sun6i_dsi_remove()
1214 if (!IS_ERR(dsi->bus_clk)) in sun6i_dsi_remove()
1215 regmap_mmio_detach_clk(dsi->regs); in sun6i_dsi_remove()
1221 { .compatible = "allwinner,sun6i-a31-mipi-dsi" },
1222 { .compatible = "allwinner,sun50i-a64-mipi-dsi" },
1231 .name = "sun6i-mipi-dsi",
1237 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
1238 MODULE_DESCRIPTION("Allwinner A31 DSI Driver");