Skip to content
Permalink
Browse files
drm/kmb: Mipi DPHY initialization changes
Fix test_mode_send and dphy_wait_fsm for 2-lane MIPI

- Fix test_mode_send when sending normal mode test codes
- Change dphy_wait_fsm to check for IDLE status rather than LOCK
  status for 2-lane MIPI

Signed-off-by: Anitha Chrisanthus <anitha.chrisanthus@intel.com>
Signed-off-by: Edmund Dea <edmund.j.dea@intel.com>
  • Loading branch information
achrisan authored and yifanli-intel committed Aug 19, 2020
1 parent e9e8570 commit 0289630c4e708652f21372eaa22ef03b3234091c
Show file tree
Hide file tree
Showing 7 changed files with 839 additions and 295 deletions.
@@ -42,6 +42,7 @@
#include "kmb_drv.h"
#include "kmb_plane.h"
#include "kmb_regs.h"
#include "kmb_dsi.h"

static void kmb_crtc_cleanup(struct drm_crtc *crtc)
{
@@ -94,23 +95,33 @@ static const struct drm_crtc_funcs kmb_crtc_funcs = {

static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
{
struct drm_display_mode *m = &crtc->state->adjusted_mode;
struct drm_device *dev = crtc->dev;
#ifdef LCD_TEST
struct drm_display_mode *m = &crtc->state->adjusted_mode;
struct videomode vm;
int vsync_start_offset;
int vsync_end_offset;
unsigned int ctrl = 0;

#endif
/* initialize mipi */
kmb_dsi_hw_init(dev);
#ifdef LCD_TEST
vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
vm.vsync_len = m->crtc_vsync_end - m->crtc_vsync_start;
vm.hfront_porch = m->crtc_hsync_start - m->crtc_hdisplay;
//vm.hfront_porch = m->crtc_hsync_start - m->crtc_hdisplay;
vm.hfront_porch = 0;
vm.hback_porch = m->crtc_htotal - m->crtc_hsync_end;
vm.hsync_len = m->crtc_hsync_end - m->crtc_hsync_start;

vsync_start_offset = m->crtc_vsync_start - m->crtc_hsync_start;
vsync_end_offset = m->crtc_vsync_end - m->crtc_hsync_end;

DRM_INFO("%s : %dactive height= %d vbp=%d vfp=%d vsync-w=%d h-active=%d h-bp=%d h-fp=%d hysnc-l=%d\n",
__func__, __LINE__, m->crtc_vdisplay,
vm.vback_porch, vm.vfront_porch,
vm.vsync_len, m->crtc_hdisplay,
vm.hback_porch, vm.hfront_porch, vm.hsync_len);
kmb_write_lcd(dev->dev_private, LCD_V_ACTIVEHEIGHT,
m->crtc_vdisplay - 1);
kmb_write_lcd(dev->dev_private, LCD_V_BACKPORCH, vm.vback_porch - 1);
@@ -145,7 +156,7 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
kmb_write_lcd(dev->dev_private, LCD_CONTROL, ctrl);

kmb_write_lcd(dev->dev_private, LCD_TIMING_GEN_TRIG, ENABLE);

#endif
/* TBD */
/* set clocks here */
}
@@ -157,7 +168,7 @@ static void kmb_crtc_atomic_enable(struct drm_crtc *crtc,

clk_prepare_enable(lcd->clk);
kmb_crtc_mode_set_nofb(crtc);
drm_crtc_vblank_on(crtc);
// drm_crtc_vblank_on(crtc);
}

static void kmb_crtc_atomic_disable(struct drm_crtc *crtc,
@@ -168,7 +179,7 @@ static void kmb_crtc_atomic_disable(struct drm_crtc *crtc,
/* always disable planes on the CRTC that is being turned off */
drm_atomic_helper_disable_planes_on_crtc(old_state, false);

drm_crtc_vblank_off(crtc);
// drm_crtc_vblank_off(crtc);
clk_disable_unprepare(lcd->clk);
}

@@ -34,6 +34,7 @@
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <drm/drm.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_probe_helper.h>
@@ -57,27 +58,27 @@ static irqreturn_t kmb_isr(int irq, void *arg);
static struct clk *clk_lcd;
static struct clk *clk_mipi;
static struct clk *clk_msscam;
static struct clk *clk_pll0out0;
static struct clk *clk_mipi_ecfg;
static struct clk *clk_mipi_cfg;

struct drm_bridge *adv_bridge;

static int kmb_display_clk_enable(void)
int kmb_display_clk_enable(void)
{
int ret = 0;

#ifdef LCD_TEST
ret = clk_prepare_enable(clk_lcd);
if (ret) {
DRM_ERROR("Failed to enable LCD clock: %d\n", ret);
return ret;
}

#endif
ret = clk_prepare_enable(clk_mipi);
if (ret) {
DRM_ERROR("Failed to enable MIPI clock: %d\n", ret);
return ret;
}

/* ret = clk_prepare_enable(clk_msscam);
if (ret) {
DRM_ERROR("Failed to enable MSSCAM clock: %d\n", ret);
@@ -178,19 +179,47 @@ static int kmb_load(struct drm_device *drm, unsigned long flags)
iounmap(dev_p->mipi_mmio);
return -ENOMEM;
}
/*testing*/
if (!request_mem_region(CPR_BASE_ADDR, 100, "cpr")) {
DRM_ERROR("failed to reserve %s registers\n", "cpr");
return -ENOMEM;
}
dev_p->cpr_mmio = ioremap_nocache(CPR_BASE_ADDR, 0x100);
if (!dev_p->cpr_mmio) {
DRM_ERROR("failed to ioremap %s registers\n", "CPR");
release_mem_region(CPR_BASE_ADDR, 100);
return -ENOMEM;
}

if (IS_ERR(dev_p->msscam_mmio)) {
DRM_ERROR("failed to map MSSCAM registers\n");
iounmap(dev_p->lcd_mmio);
iounmap(dev_p->mipi_mmio);
return -ENOMEM;
}



#define KMB_CLOCKS
#ifdef KMB_CLOCKS
/* Enable display clocks*/
clk_lcd = clk_get(&pdev->dev, "clk_lcd");
if (IS_ERR(clk_lcd)) {
DRM_ERROR("clk_get() failed clk_lcd\n");
goto setup_fail;
}

clk_mipi = clk_get(&pdev->dev, "clk_mipi");
if (IS_ERR(clk_mipi)) {
DRM_ERROR("clk_get() failed clk_mipi\n");
goto setup_fail;
}
clk_pll0out0 = clk_get(&pdev->dev, "clk_pll0_out0");
if (IS_ERR(clk_pll0out0))
DRM_ERROR("clk_get() failed clk_pll0_out0\n");

if (clk_pll0out0)
DRM_INFO("Get clk_pll0out0 = %ld\n",
clk_get_rate(clk_pll0out0));

clk_mipi_ecfg = clk_get(&pdev->dev, "clk_mipi_ecfg");
if (IS_ERR(clk_mipi_ecfg)) {
@@ -204,8 +233,7 @@ static int kmb_load(struct drm_device *drm, unsigned long flags)
goto setup_fail;
}

ret = kmb_display_clk_enable();

#ifdef LCD_TEST
/* Set LCD clock to 200 Mhz*/
DRM_INFO("Get clk_lcd before set = %ld\n", clk_get_rate(clk_lcd));
ret = clk_set_rate(clk_lcd, KMB_LCD_DEFAULT_CLK);
@@ -216,10 +244,11 @@ static int kmb_load(struct drm_device *drm, unsigned long flags)
DRM_INFO("Setting LCD clock to %d Mhz ret = %d\n",
KMB_LCD_DEFAULT_CLK/1000000, ret);
DRM_INFO("Get clk_lcd after set = %ld\n", clk_get_rate(clk_lcd));

#endif
/* Set MIPI clock to 24 Mhz*/
DRM_INFO("Get clk_mipi before set = %ld\n", clk_get_rate(clk_mipi));
ret = clk_set_rate(clk_mipi, KMB_MIPI_DEFAULT_CLK);
DRM_INFO("Get clk_mipi after set = %ld\n", clk_get_rate(clk_mipi));
if (clk_get_rate(clk_mipi) != KMB_MIPI_DEFAULT_CLK) {
DRM_ERROR("failed to set to clk_mipi to %d\n",
KMB_MIPI_DEFAULT_CLK);
@@ -230,10 +259,10 @@ static int kmb_load(struct drm_device *drm, unsigned long flags)
DRM_INFO("Get clk_mipi after set = %ld\n", clk_get_rate(clk_mipi));

clk = clk_get_rate(clk_mipi_ecfg);
if (clk != KMB_MIPI_DEFAULT_CLK) {
if (clk != KMB_MIPI_DEFAULT_CFG_CLK) {
/* Set MIPI_ECFG clock to 24 Mhz*/
DRM_INFO("Get clk_mipi_ecfg before set = %ld\n", clk);
ret = clk_set_rate(clk_mipi_ecfg, KMB_MIPI_DEFAULT_CLK);
ret = clk_set_rate(clk_mipi_ecfg, KMB_MIPI_DEFAULT_CFG_CLK);
clk = clk_get_rate(clk_mipi_ecfg);
if (clk != KMB_MIPI_DEFAULT_CLK) {
DRM_ERROR("failed to set to clk_mipi_ecfg to %d\n",
@@ -242,27 +271,29 @@ static int kmb_load(struct drm_device *drm, unsigned long flags)
}
DRM_INFO("Setting MIPI_ECFG clock tp %d Mhz ret = %d\n",
KMB_MIPI_DEFAULT_CLK/1000000, ret);
DRM_INFO("Get clk_mipi_ecfg after set = %ld\n", clk);
}

clk = clk_get_rate(clk_mipi_cfg);
if (clk != KMB_MIPI_DEFAULT_CLK) {
if (clk != KMB_MIPI_DEFAULT_CFG_CLK) {
/* Set MIPI_CFG clock to 24 Mhz*/
DRM_INFO("Get clk_mipi_cfg before set = %ld\n", clk);
ret = clk_set_rate(clk_mipi_cfg, 24000000);
clk = clk_get_rate(clk_mipi_cfg);
if (clk != KMB_MIPI_DEFAULT_CLK) {
if (clk != KMB_MIPI_DEFAULT_CFG_CLK) {
DRM_ERROR("failed to set to clk_mipi_cfg to %d\n",
KMB_MIPI_DEFAULT_CLK);
KMB_MIPI_DEFAULT_CFG_CLK);
goto setup_fail;
}
DRM_INFO("Setting MIPI_CFG clock tp 24Mhz ret = %d\n", ret);
DRM_INFO("Get clk_mipi_cfg after set = %ld\n", clk);
}

ret = kmb_display_clk_enable();

/* enable MSS_CAM_CLK_CTRL for MIPI TX and LCD */
kmb_set_bitmask_msscam(dev_p, MSS_CAM_CLK_CTRL, 0xfff);
kmb_set_bitmask_msscam(dev_p, MSS_CAM_RSTN_CTRL, 0xfff);
kmb_set_bitmask_msscam(dev_p, MSS_CAM_CLK_CTRL, 0x1fff);
kmb_set_bitmask_msscam(dev_p, MSS_CAM_RSTN_CTRL, 0xffffffff);
#endif //KMB_CLOCKS
#ifdef WIP
/* Register irqs here - section 17.3 in databook
* lists LCD at 79 and 82 for MIPI under MSS CPU -
@@ -312,6 +343,7 @@ static int kmb_load(struct drm_device *drm, unsigned long flags)
goto setup_fail;
}


/* Initialize MIPI DSI */
ret = kmb_dsi_init(drm, adv_bridge);
if (ret) {
@@ -340,9 +372,17 @@ static int kmb_load(struct drm_device *drm, unsigned long flags)
return ret;
}

int kmb_atomic_helper_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
if (!state)
return 0;
return drm_atomic_helper_check(dev, state);
}

static const struct drm_mode_config_funcs kmb_mode_config_funcs = {
.fb_create = drm_gem_fb_create,
.atomic_check = drm_atomic_helper_check,
.atomic_check = kmb_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};

@@ -504,13 +544,14 @@ static int kmb_probe(struct platform_device *pdev)
* afterwards and the bridge can be successfully attached.
*/
adv_bridge = kmb_dsi_host_bridge_init(dev);
#ifndef FCCTEST
if (adv_bridge == ERR_PTR(-EPROBE_DEFER))
return -EPROBE_DEFER;
else if (IS_ERR(adv_bridge)) {
DRM_ERROR("probe failed to initialize DSI host bridge\n");
return PTR_ERR(adv_bridge);
}

#endif
/* Create DRM device */
drm = drm_dev_alloc(&kmb_driver, dev);
if (IS_ERR(drm))
@@ -535,13 +576,6 @@ static int kmb_probe(struct platform_device *pdev)

/* Set the CRTC's port so that the encoder component can find it */
lcd->crtc.port = of_graph_get_port_by_id(dev->of_node, 0);

ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (ret < 0) {
DRM_ERROR("failed to initialize vblank\n");
goto err_vblank;
}

drm_mode_config_reset(drm);
drm_kms_helper_poll_init(drm);

@@ -551,13 +585,13 @@ static int kmb_probe(struct platform_device *pdev)
if (ret)
goto err_register;

drm_fbdev_generic_setup(drm, 32);

#ifndef FCCTEST
// drm_fbdev_generic_setup(drm, 32);
#endif
return 0;

err_register:
drm_kms_helper_poll_fini(drm);
err_vblank:
pm_runtime_disable(drm->dev);
err_free:
drm_mode_config_cleanup(drm);
@@ -28,16 +28,19 @@

#include "kmb_regs.h"

/*#define FCCTEST*/
#define KMB_MAX_WIDTH 1920 /*max width in pixels */
#define KMB_MAX_HEIGHT 1080 /*max height in pixels */
#define KMB_LCD_DEFAULT_CLK 24000000
#define KMB_LCD_DEFAULT_CLK 250000000
#define KMB_MIPI_DEFAULT_CLK 24000000
#define KMB_MIPI_DEFAULT_CFG_CLK 24000000

struct kmb_drm_private {
struct drm_device drm;
void __iomem *lcd_mmio;
void __iomem *mipi_mmio;
void __iomem *msscam_mmio;
void __iomem *cpr_mmio;
unsigned char n_layers;
struct clk *clk;
struct drm_crtc crtc;
@@ -88,12 +91,23 @@ static inline void kmb_write_bits(struct kmb_drm_private *lcd,
reg_val |= (value << offset);
writel(reg_val, lcd->mmio + reg);
}
static inline void kmb_write(unsigned int reg, u32 value)
{
writel(value, reg);
}

static inline u32 kmb_read(unsigned int reg)
{
return readl(reg);
}
#endif

static inline void kmb_write_lcd(struct kmb_drm_private *dev_p,
unsigned int reg, u32 value)
{
#ifdef LCD_TEST
writel(value, (dev_p->lcd_mmio + reg));
#endif
}

static inline void kmb_write_mipi(struct kmb_drm_private *dev_p,
@@ -124,23 +138,30 @@ static inline void kmb_set_bitmask_msscam(struct kmb_drm_private *dev_p,

static inline u32 kmb_read_lcd(struct kmb_drm_private *dev_p, unsigned int reg)
{
#ifdef LCD_TEST
return readl(dev_p->lcd_mmio + reg);
#endif
return 0;
}

static inline void kmb_set_bitmask_lcd(struct kmb_drm_private *dev_p,
unsigned int reg, u32 mask)
{
#ifdef LCD_TEST
u32 reg_val = kmb_read_lcd(dev_p, reg);

kmb_write_lcd(dev_p, reg, (reg_val | mask));
#endif
}

static inline void kmb_clr_bitmask_lcd(struct kmb_drm_private *dev_p,
unsigned int reg, u32 mask)
{
#ifdef LCD_TEST
u32 reg_val = kmb_read_lcd(dev_p, reg);

kmb_write_lcd(dev_p, reg, (reg_val & (~mask)));
#endif
}

static inline u32 kmb_read_mipi(struct kmb_drm_private *dev_p, unsigned int reg)

0 comments on commit 0289630

Please sign in to comment.