imx8_fb_drv: MIPI DSI display support

- support for Northwest Logic MIPI DSI bridge
- support for Radium panel (NXP MX8_DSI_OLED1)
- new 'DSI-1' connector in driver config file

issue #3900
This commit is contained in:
Sebastian Sumpf 2020-06-11 16:21:51 +02:00 committed by Christian Helmuth
parent 27f705bc48
commit 664b861f9d
15 changed files with 1112 additions and 150 deletions

View File

@ -18,6 +18,7 @@ linux-x.x.x/drivers/gpu/drm/drm_gem.c
linux-x.x.x/drivers/gpu/drm/drm_gem_cma_helper.c
linux-x.x.x/drivers/gpu/drm/drm_gem_framebuffer_helper.c
linux-x.x.x/drivers/gpu/drm/drm_internal.h
linux-x.x.x/drivers/gpu/drm/drm_mipi_dsi.c
linux-x.x.x/drivers/gpu/drm/drm_mm.c
linux-x.x.x/drivers/gpu/drm/drm_mode_config.c
linux-x.x.x/drivers/gpu/drm/drm_mode_object.c
@ -31,8 +32,10 @@ linux-x.x.x/drivers/gpu/drm/drm_property.c
linux-x.x.x/drivers/gpu/drm/drm_rect.c
linux-x.x.x/drivers/gpu/drm/drm_vblank.c
linux-x.x.x/drivers/gpu/drm/drm_vma_manager.c
linux-x.x.x/drivers/gpu/drm/bridge/nwl-dsi.c
linux-x.x.x/drivers/gpu/drm/imx/imx-drm.h
linux-x.x.x/drivers/gpu/drm/imx/imx-drm-core.c
linux-x.x.x/drivers/gpu/drm/imx/nwl_dsi-imx.c
linux-x.x.x/drivers/gpu/drm/imx/dcss/dcss-crtc.c
linux-x.x.x/drivers/gpu/drm/imx/dcss/dcss-crtc.h
linux-x.x.x/drivers/gpu/drm/imx/dcss/dcss-kms.c
@ -61,6 +64,7 @@ linux-x.x.x/drivers/gpu/drm/imx/hdp/ss28fdsoi_hdmitx_table.c
linux-x.x.x/drivers/gpu/drm/imx/hdp/ss28fdsoi_hdmitx_table.h
linux-x.x.x/drivers/gpu/drm/imx/hdp/t28hpc_hdmitx_table.c
linux-x.x.x/drivers/gpu/drm/imx/hdp/t28hpc_hdmitx_table.h
linux-x.x.x/drivers/gpu/drm/panel/panel-raydium-rm67191.c
linux-x.x.x/drivers/gpu/imx/dcss/dcss-common.c
linux-x.x.x/drivers/gpu/imx/dcss/dcss-blkctl.c
linux-x.x.x/drivers/gpu/imx/dcss/dcss-ctxld.c
@ -111,6 +115,7 @@ linux-x.x.x/drivers/mxc/hdp/source_vif.h
linux-x.x.x/drivers/mxc/hdp/util.c
linux-x.x.x/drivers/mxc/hdp/util.h
linux-x.x.x/drivers/mxc/hdp-cec/imx-hdp-cec.h
linux-x.x.x/drivers/phy/phy-mixel-mipi-dsi.c
linux-x.x.x/drivers/video/hdmi.c
linux-x.x.x/include/asm-generic/atomic64.h
linux-x.x.x/include/asm-generic/bitops/__ffs.h
@ -145,6 +150,7 @@ linux-x.x.x/include/drm/drm_gem_framebuffer_helper.h
linux-x.x.x/include/drm/drm_hashtab.h
linux-x.x.x/include/drm/drm_hdcp.h
linux-x.x.x/include/drm/drm_ioctl.h
linux-x.x.x/include/drm/drm_mipi_dsi.h
linux-x.x.x/include/drm/drm_mm.h
linux-x.x.x/include/drm/drm_mode_config.h
linux-x.x.x/include/drm/drm_mode_object.h
@ -163,6 +169,7 @@ linux-x.x.x/include/drm/drm_property.h
linux-x.x.x/include/drm/drm_rect.h
linux-x.x.x/include/drm/drm_vblank.h
linux-x.x.x/include/drm/drm_vma_manager.h
linux-x.x.x/include/drm/bridge/nwl_dsi.h
linux-x.x.x/include/linux/irqchip/chained_irq.h
linux-x.x.x/include/linux/busfreq-imx.h
linux-x.x.x/include/linux/component.h
@ -183,12 +190,16 @@ linux-x.x.x/include/linux/mod_devicetable.h
linux-x.x.x/include/linux/of_graph.h
linux-x.x.x/include/linux/pm_runtime.h
linux-x.x.x/include/linux/pm_wakeirq.h
linux-x.x.x/include/linux/phy.h
linux-x.x.x/include/linux/radix-tree.h
linux-x.x.x/include/linux/ratelimit.h
linux-x.x.x/include/linux/rbtree_augmented.h
linux-x.x.x/include/linux/rbtree.h
linux-x.x.x/include/linux/sort.h
linux-x.x.x/include/linux/vga_switcheroo.h
linux-x.x.x/include/linux/mfd/syscon/imx8mq-iomuxc-gpr.h
linux-x.x.x/include/linux/phy/phy.h
linux-x.x.x/include/linux/phy/phy-mixel-mipi-dsi.h
linux-x.x.x/include/soc/imx8/sc/ipc.h
linux-x.x.x/include/soc/imx8/sc/scfw.h
linux-x.x.x/include/soc/imx8/sc/sci.h
@ -204,6 +215,7 @@ linux-x.x.x/include/uapi/linux/i2c.h
linux-x.x.x/include/uapi/linux/media-bus-format.h
linux-x.x.x/include/uapi/linux/swab.h
linux-x.x.x/include/video/display_timing.h
linux-x.x.x/include/video/mipi_display.h
linux-x.x.x/include/video/of_videomode.h
linux-x.x.x/include/video/videomode.h
linux-x.x.x/include/video/viv-metadata.h

View File

@ -8,20 +8,27 @@ SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/dma-buf/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/i2c/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/base/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/gpu/drm/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/gpu/drm/bridge/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/gpu/drm/imx/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/gpu/drm/imx/dcss/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/gpu/drm/imx/hdp/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/gpu/drm/panel/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/gpu/imx/dcss/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/irqchip/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/mxc/hdp/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/phy/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/video/*.c))
SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/lib/*.c))
CC_OPT_nwl-dsi += -DMOD_SUFFIX=_bridge
#
# Linux sources are C89 with GNU extensions
#
CC_C_OPT += -std=gnu89
#
# Reduce build noise of compiling contrib code
#
@ -34,12 +41,15 @@ vpath %.c $(LX_CONTRIB_DIR)/drivers/base
vpath %.c $(LX_CONTRIB_DIR)/drivers/dma-buf
vpath %.c $(LX_CONTRIB_DIR)/drivers/i2c
vpath %.c $(LX_CONTRIB_DIR)/drivers/gpu/drm
vpath %.c $(LX_CONTRIB_DIR)/drivers/gpu/drm/bridge
vpath %.c $(LX_CONTRIB_DIR)/drivers/gpu/drm/imx
vpath %.c $(LX_CONTRIB_DIR)/drivers/gpu/drm/imx/dcss
vpath %.c $(LX_CONTRIB_DIR)/drivers/gpu/drm/imx/hdp
vpath %.c $(LX_CONTRIB_DIR)/drivers/gpu/drm/panel
vpath %.c $(LX_CONTRIB_DIR)/drivers/gpu/imx/dcss
vpath %.c $(LX_CONTRIB_DIR)/drivers/irqchip
vpath %.c $(LX_CONTRIB_DIR)/drivers/mxc/hdp
vpath %.c $(LX_CONTRIB_DIR)/drivers/phy
vpath %.c $(LX_CONTRIB_DIR)/drivers/video
vpath %.c $(LX_CONTRIB_DIR)/lib

View File

@ -1,23 +1,13 @@
dcss_blkctl.patch
diff --git a/drivers/gpu/imx/dcss/dcss-blkctl.c b/drivers/gpu/imx/dcss/dcss-blkctl.c
index 2f13b33..63d48bf 100644
index 2f13b33..a4b0620 100644
--- a/drivers/gpu/imx/dcss/dcss-blkctl.c
+++ b/drivers/gpu/imx/dcss/dcss-blkctl.c
@@ -115,10 +115,14 @@ int dcss_blkctl_init(struct dcss_soc *dcss, unsigned long blkctl_base)
disp_dev = of_get_property(node, "disp-dev", &len);
if (!disp_dev || !strncmp(disp_dev, "hdmi_disp", 9))
blkctl->hdmi_output = true;
-
+#if 0
+ /*
+ * XXX: for some reason 'HDMI_MIPI_CLK_SEL' does not work with SOC revision
+ * 0x20 and Genode
+ */
if (imx8_get_soc_revision() >= B0_SILICON_ID)
blkctl->clk_setting = HDMI_MIPI_CLK_SEL;
-
+#endif
dcss_blkctl_cfg(dcss);
@@ -81,7 +81,7 @@ void dcss_blkctl_cfg(struct dcss_soc *dcss)
struct dcss_blkctl_priv *blkctl = dcss->blkctl_priv;
return 0;
if (blkctl->hdmi_output)
- dcss_writel((blkctl->clk_setting ^ HDMI_MIPI_CLK_SEL),
+ dcss_writel((blkctl->clk_setting),
blkctl->base_reg + DCSS_BLKCTL_CONTROL0);
else
dcss_writel((blkctl->clk_setting ^ HDMI_MIPI_CLK_SEL) |

View File

@ -1,7 +1,5 @@
imx_drm_core.patch
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 76b782c..a2c3a76 100644
index 453100d..05ef413 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -43,7 +43,9 @@ static void imx_drm_driver_lastclose(struct drm_device *drm)
@ -14,7 +12,7 @@ index 76b782c..a2c3a76 100644
}
DEFINE_DRM_GEM_CMA_FOPS(imx_drm_driver_fops);
@@ -120,6 +122,17 @@ static int compare_of(struct device *dev, void *data)
@@ -120,6 +122,20 @@ static int compare_of(struct device *dev, void *data)
{
struct device_node *np = data;
@ -26,13 +24,16 @@ index 76b782c..a2c3a76 100644
+ (strncmp(np->name, "hdmi", strlen(np->name)) == 0))
+ return 1;
+
+ if (strcmp(dev->driver->name, "nwl_dsi-imx") == 0 && strcmp(np->name, "mipi_dsi") == 0)
+ return 1;
+
+ return 0;
+
+#if 0
/* Special case for DI, dev->of_node may not be set yet */
if (strcmp(dev->driver->name, "imx-ipuv3-crtc") == 0) {
struct ipu_client_platformdata *pdata = dev->platform_data;
@@ -161,6 +174,7 @@ static int compare_of(struct device *dev, void *data)
@@ -161,6 +177,7 @@ static int compare_of(struct device *dev, void *data)
}
return dev->of_node == np;
@ -40,7 +41,7 @@ index 76b782c..a2c3a76 100644
}
static const char *const imx_drm_dpu_comp_parents[] = {
@@ -416,8 +430,10 @@ static void imx_drm_unbind(struct device *dev)
@@ -416,8 +433,10 @@ static void imx_drm_unbind(struct device *dev)
drm_kms_helper_poll_fini(drm);

View File

@ -1 +1 @@
173719007927a108a9558e727b8c9b388f3159a2
12e42f3a812a4d84a068782f0a65936e7e7de884

View File

@ -1 +1 @@
2020-09-16 20a4af22bc5eb3b01c66324e77645662e8801b1a
2020-06-12 ce8ce6fad1a020458658f5bb86e582eab4758dee

View File

@ -64,18 +64,44 @@
parent="system_pll1_clk"
rate="400000000"
driver_name="rtrm"/>
<clock name="video2_pll2_clk"
parent="27m_ref_clk"
driver_name="pix"/>
<clock name="video_pll1_clk"
parent="25m_ref_clk"
rate="1200000000" />
<clock name="display_dtrc_clk_root"
driver_name="dtrc"/>
<clock name="dc_pixel_clk_root"
parent="video_pll1_clk"
rate="594000000"/>
rate="120000000"
driver_name="pix"/>
<property name="compatible" value="nxp,imx8mq-dcss"/>
<property name="disp-dev" value="hdmi_disp"/>
</device>
<!-- CAUTION: System reset controller access is currently required by
mipi_dsi -->
<device name="src">
<io_mem address="0x30390000" size="0x10000"/>
</device>
<device name="mipi_dsi">
<io_mem address="0x30a00000" size="0x1000"/>
<irq number="66"/>
<power-domain name="mipi"/>
<clock name="mipi_dsi_phy_ref_clk_root"
parent="video_pll1_clk"
rate="24000000"
driver_name="phy_ref"/>
<clock name="mipi_dsi_esc_rx_clk_root"
parent="system_pll1_div10"
rate="80000000"
driver_name="rx_esc"/>
<clock name="mipi_dsi_core_clk_root"
parent="system_pll1_div3"
rate="266000000"
driver_name="core"/>
<property name="compatible" value="fsl,imx8mq-mipi-dsi_drm"/>
</device>
<device name="hdmi">
<io_mem address="0x32c00000" size="0x100000"/>
<io_mem address="0x32e40000" size="0x40000"/>
@ -89,6 +115,8 @@
<policy label="fb_drv -> ">
<device name="dcss"/>
<device name="hdmi"/>
<device name="mipi_dsi"/>
<device name="src"/>
</policy>
</config>
<route> <any-service> <parent/> </any-service> </route>
@ -104,7 +132,13 @@
</config>
<route>
<service name="Report"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
<service name="RM"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Timer"> <parent/> </service>
<service name="Platform"> <child name="platform_drv"/> </service>
</route>
</start>
@ -115,17 +149,21 @@
<route>
<service name="ROM" label="report"> <child name="report_rom"/> </service>
<service name="Event"> <parent/> </service>
<any-service> <parent/> <any-child/> </any-service>
<service name="RM"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Timer"> <parent/> </service>
<service name="Usb"> <child name="usb_drv"/> </service>
</route>
</start>
<start name="fb_drv" caps="250">
<binary name="imx8_fb_drv"/>
<resource name="RAM" quantum="80M"/>
<resource name="RAM" quantum="40M"/>
<route>
<service name="ROM" label="config"> <parent label="fb_drv.config"/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>

View File

@ -1,3 +1,4 @@
<config>
<connector name="HDMI-A-1" width="1920" height="1080" hz="60" enabled="true"/>
<connector name="DSI-1" width="1080" height="1920" hz="60" enabled="false"/>
</config>

View File

@ -1 +1 @@
2020-09-16 fad4ed0507a29556deddce535fc45963241f856d
2020-06-12 b9cbb9da87bc382d55c3345bcb5da6b845b57aec

View File

@ -121,6 +121,29 @@ void drm_dev_unregister(struct drm_device *dev)
}
/***********************
** linux/drm_panel.h **
***********************/
void drm_panel_init(struct drm_panel *panel)
{
TRACE;
}
void drm_panel_remove(struct drm_panel *panel)
{
TRACE_AND_STOP;
}
int drm_panel_detach(struct drm_panel *panel)
{
TRACE;
return -1;
}
/*****************************************
** drivers/gpu/drm/drm_fb_cma_helper.c **
*****************************************/
@ -295,12 +318,6 @@ void clk_disable_unprepare(struct clk *clk)
TRACE;
}
int clk_prepare_enable(struct clk *clk)
{
TRACE;
return 0;
}
/******************
** linux/gpio.h **
@ -373,6 +390,7 @@ bool is_of_node(const struct fwnode_handle *fwnode)
}
/************************
** linux/pm_runtime.h **
************************/
@ -411,6 +429,53 @@ ktime_t ktime_get_real(void)
}
/***********************
** linux/of_device.h **
***********************/
int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
{
TRACE_AND_STOP;
return -ENODEV;
}
/********************
** linux/device.h **
********************/
void device_initialize(struct device *dev)
{
TRACE;
}
void device_unregister(struct device *dev)
{
TRACE;
}
/***********************
** video/videomode.h **
***********************/
void videomode_from_timing(const struct display_timing *dt, struct videomode *vm)
{
TRACE_AND_STOP;
}
/***********************
** linux/backlight.h **
***********************/
int backlight_disable(struct backlight_device *bd)
{
TRACE_AND_STOP;
return -1;
}
/*************************
** linux/dma-mapping.h **
*************************/
@ -434,6 +499,76 @@ int dma_mmap_wc(struct device *dev,
}
/*****************
** linux/phy.h **
*****************/
struct phy;
struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
struct device_node *children,
struct module *owner,
struct phy * (*of_xlate)(struct device *dev,
struct of_phandle_args *args))
{
TRACE;
return NULL;
}
struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args *args)
{
TRACE_AND_STOP;
return NULL;
}
int phy_power_off(struct phy *phy)
{
TRACE;
return -1;
}
int phy_exit(struct phy *phy)
{
TRACE;
return -1;
}
/***********************
** linux/interrupt.h **
***********************/
void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
{
TRACE;
}
/********************************
** linux/unaligned/generic.h **
********************************/
u32 get_unaligned_le32(const void *p)
{
TRACE_AND_STOP;
return 0;
}
/********************
** linux/regmap.h **
********************/
struct regmap;
int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
{
TRACE_AND_STOP;
return 0;
}
/************************
** linux/pm-runtime.h **
************************/
@ -561,12 +696,6 @@ loff_t noop_llseek(struct file *file, loff_t offset, int whence)
return -1;
}
int of_alias_get_id(struct device_node *np, const char *stem)
{
TRACE_AND_STOP;
return -ENOSYS;
}
int of_irq_get(struct device_node *dev, int index)
{
TRACE_AND_STOP;
@ -592,8 +721,8 @@ void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
int PTR_ERR_OR_ZERO(__force const void *ptr)
{
TRACE_AND_STOP;
return -1;
TRACE;
return 0;
}
void up_read(struct rw_semaphore *sem)

View File

@ -111,14 +111,17 @@ LX_MUTEX_INIT_DECLARE(component_mutex);
** asm-generic/io.h **
**********************/
#include <lx_emul/mmio.h>
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
return *(const volatile u32 __force *) addr;
return readl(addr);
}
static inline void __raw_writel(u32 b, volatile void __iomem *addr)
{
*(volatile u32 __force *) addr = b;
writel(b, addr);
}
@ -756,6 +759,13 @@ enum rpm_status {
RPM_SUSPENDED,
};
#define pm_generic_suspend NULL
#define pm_generic_resume NULL
#define pm_generic_freeze NULL
#define pm_generic_thaw NULL
#define pm_generic_poweroff NULL
#define pm_generic_restore NULL
/***********************
** linux/pm_domain.h **
@ -784,6 +794,7 @@ struct bus_type
const char *name;
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
@ -855,8 +866,12 @@ struct device_attribute {
#define dev_printk(level, dev, format, arg...) \
lx_printf("dev_printk: " format , ## arg)
#if DEBUG_DRIVER
#define dev_dbg(dev, format, arg...) \
lx_printf("dev_dbg: " format, ## arg)
#else
#define dev_dbg(dev, format, arg...)
#endif
#define dev_err_ratelimited(dev, fmt, ...) \
dev_err(dev, fmt, ##__VA_ARGS__)
@ -869,7 +884,10 @@ struct device_driver
const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;
const struct dev_pm_ops *pm;
int (*probe) (struct device *dev);
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
};
int driver_register(struct device_driver *drv);
@ -899,9 +917,15 @@ int device_add(struct device *dev);
int device_register(struct device *dev);
void device_unregister(struct device *dev);
void device_initialize(struct device *dev);
const char *dev_name(const struct device *dev);
struct device *bus_find_device(struct bus_type *bus, struct device *start, void *data,
int (*match)(struct device *dev, void *data));
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
void *data, int (*fn)(struct device_driver *, void *));
@ -913,6 +937,7 @@ struct acpi_device;
void devm_kfree(struct device *dev, void *p);
void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
void *devm_kcalloc(struct device *dev, size_t n, size_t size, gfp_t flags);
typedef void (*dr_release_t)(struct device *dev, void *res);
typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data);
@ -931,6 +956,9 @@ void *devres_open_group(struct device *dev, void *id, gfp_t gfp);
int devres_release_group(struct device *dev, void *id);
void devres_remove_group(struct device *dev, void *id);
void *devres_find(struct device *dev, dr_release_t release,
dr_match_t match, void *match_data);
int dev_to_node(struct device *dev);
@ -938,9 +966,6 @@ int dev_to_node(struct device *dev);
** linux/io.h **
****************/
#define writel(value, addr) (*(volatile uint32_t *)(addr) = (value))
#define readl(addr) (*(volatile uint32_t *)(addr))
#define readl_relaxed readl
#define writel_relaxed(v, a) writel(v, a)
@ -1163,6 +1188,13 @@ extern struct page *shmem_read_mapping_page( struct address_space *mapping, pgof
struct file *shmem_file_setup(const char *, loff_t, unsigned long);
/********************************
** linux/unaligned/generic.h **
********************************/
u32 get_unaligned_le32(const void *p);
/*****************
** linux/i2c.h **
*****************/
@ -1170,10 +1202,23 @@ struct file *shmem_file_setup(const char *, loff_t, unsigned long);
enum i2c_slave_event { DUMMY };
/***********************
** uapi/linux/uuid.h **
***********************/
typedef struct {
__u8 b[16];
} uuid_le;
/****************
** linux/of.h **
****************/
struct of_phandle_args;
#include <linux/mod_devicetable.h>
int of_alias_get_id(struct device_node *np, const char *stem);
struct device_node *of_node_get(struct device_node *node);
void of_node_put(struct device_node *);
@ -1187,6 +1232,10 @@ int of_property_read_u32_index(const struct device_node *, const char *, u32,
for (child = of_get_next_child(parent, NULL); child != NULL; \
child = of_get_next_child(parent, child))
#define for_each_available_child_of_node(parent, child) \
for (child = of_get_next_child(parent, NULL); child != NULL; \
child = of_get_next_child(parent, child))
struct property {
const char * name;
void * value;
@ -1216,6 +1265,10 @@ int of_property_read_string(const struct device_node *np, const char *propname,
const char **out_string);
int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value);
struct property *of_find_property(const struct device_node *np,
const char *name, int *lenp);
int of_modalias_node(struct device_node *node, char *modalias, int len);
bool is_of_node(const struct fwnode_handle *fwnode);
#define to_of_node(__fwnode) \
@ -1228,6 +1281,9 @@ bool is_of_node(const struct fwnode_handle *fwnode);
NULL; \
})
struct device_node *of_get_child_by_name(const struct device_node *node,
const char *name);
/***********************
** linux/of_device.h **
@ -1238,6 +1294,28 @@ const void *of_device_get_match_data(const struct device *dev);
const struct of_device_id *of_match_device(const struct of_device_id *matches,
const struct device *dev);
int of_driver_match_device(struct device *dev, const struct device_driver *drv);
int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env);
/**************************
** linux/of_videomode.h **
**************************/
struct videomode;
int of_get_videomode(struct device_node *np, struct videomode *vm, int index);
/***********************
** video/videomode.h **
***********************/
struct display_timing;
void videomode_from_timing(const struct display_timing *dt, struct videomode *vm);
/******************
** linux/acpi.h **
@ -1284,6 +1362,51 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
void gpio_set_value(unsigned int gpio, int value);
/***************************
** linux/gpio/consumer.h **
***************************/
#define GPIOD_FLAGS_BIT_DIR_SET BIT(0)
#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2)
enum gpiod_flags {
GPIOD_OUT_HIGH = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |
GPIOD_FLAGS_BIT_DIR_VAL
};
struct gpio_desc
{
u32 pin;
};
struct gpio_desc *
devm_gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags);
void gpiod_set_value(struct gpio_desc *desc, int value);
/********************
** linux/regmap.h **
********************/
struct regmap
{
u8 *base;
};
int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
int regmap_update_bits(struct regmap *map, unsigned reg, unsigned mask,
unsigned val);
/************************
** linux/mfd/syscon.h **
************************/
struct regmap *syscon_regmap_lookup_by_phandle( struct device_node *np, const char *property);
/* needed by drivers/gpu/drm/drm_modes.c */
#include <linux/list_sort.h>
@ -1544,6 +1667,58 @@ int device_property_read_u32(struct device *, const char *, u32 *);
void call_rcu(struct rcu_head *, void (*)(struct rcu_head *));
/***********************
** linux/backlight.h **
***********************/
enum backlight_type {
BACKLIGHT_RAW = 1,
};
struct backlight_properties
{
int brightness;
int max_brightness;
enum backlight_type type;
};
struct backlight_ops;
struct backlight_device
{
struct backlight_properties props;
struct backlight_ops const *ops;
struct device dev;
};
struct backlight_ops {
int (*update_status)(struct backlight_device *);
int (*get_brightness)(struct backlight_device *);
};
int backlight_enable(struct backlight_device *bd);
int backlight_disable(struct backlight_device *bd);
void *bl_get_data(struct backlight_device *bl_dev);
struct backlight_device *
devm_backlight_device_register(struct device *dev, const char *name,
struct device *parent, void *devdata,
const struct backlight_ops *ops,
const struct backlight_properties *props);
/****************************
** drivers/phy/phy-core.c **
****************************/
void devm_phy_consume(struct device *dev, void *res);
/***********************
** linux/backlight.h **
***********************/
struct drm_panel;
/************************
** drm/drm_os_linux.h **
************************/
@ -1622,7 +1797,9 @@ static inline void *irq_desc_get_handler_data(struct irq_desc *desc)
#define CONFIG_MMU 1
#define CONFIG_OF 1
#define CONFIG_VIDEOMODE_HELPERS 1
#define CONFIG_PHY_MIXEL_MIPI_DSI 1
#define CONFIG_GENERIC_PHY 1
#define CONFIG_DRM_PANEL 1
/**************************
** Dummy trace funtions **
@ -1653,6 +1830,7 @@ void enable_irq(unsigned int);
void disable_irq(unsigned int);
int disable_irq_nosync(unsigned int);
void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
/*****************************
** linux/platform_device.h **
@ -1704,30 +1882,32 @@ struct platform_driver {
int platform_driver_register(struct platform_driver *);
void platform_driver_unregister(struct platform_driver *);
#ifndef MOD_SUFFIX
#define MOD_SUFFIX
#endif
#define _MOD_CONCAT(a,b,c) a##b##c
#define MOD_CONCAT(a,b,c) _MOD_CONCAT(a,b,c)
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
static int __init MOD_CONCAT(__driver, MOD_SUFFIX, _init)(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
int MOD_CONCAT(module_##__driver, MOD_SUFFIX, _init)() { \
return MOD_CONCAT(__driver, MOD_SUFFIX, _init)(); } \
static void __exit MOD_CONCAT(__driver, MOD_SUFFIX, _exit)(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);
void MOD_CONCAT(module_exit_##__driver, MOD_SUFFIX, _exit)() { \
MOD_CONCAT(__driver, MOD_SUFFIX, _exit)(); }
#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)
/***********************
** uapi/linux/uuid.h **
***********************/
typedef struct {
__u8 b[16];
} uuid_le;
/************************
** linux/cpuhotplug.h **
@ -1743,7 +1923,8 @@ enum cpuhp_state {
*******************/
enum {
SZ_4K = 0x00001000,
SZ_256 = 0x00000100,
SZ_4K = 0x00001000,
SZ_16K = 0x00004000,
};
@ -1763,11 +1944,27 @@ enum {
IOMEM_END_HDMI_CRS = 0x33ffff,
IOMEM_BASE_HDMI_RST = 0x340000,
IOMEM_END_HDMI_RST = 0x34000f,
IOMEM_BASE_MIPI_DSI = 0x400000,
IOMEM_BASE_MIPI_DPHY = 0x400300,
IOMEM_END_MIPI_DSI = 0x400fff,
IRQ_IRQSTEER = 32,
IRQ_HDMI_IN = 33,
IRQ_HDMI_OUT = 34
IRQ_HDMI_OUT = 34,
IRQ_MIPI_DSI = 35,
IOMEM_BASE_SRC = 0x410000,
IOMEM_END_SRC = 0xf1ffff,
};
/************************************
** drivers/gpu/drm/drm_mipi_dsi.c **
************************************/
//XXX: init in startup code before drm_mipi_dsi.c
LX_MUTEX_INIT_DECLARE(host_lock);
#define host_lock LX_MUTEX(host_lock)
#include <lx_emul/extern_c_end.h>
#endif /* _LX_EMUL_H_ */

View File

@ -19,7 +19,7 @@
#define TRACE_AND_STOP \
do { \
lx_printf("%s not implemented\n", __func__); \
lx_printf("%s not implemented called from %p\n", __func__, __builtin_return_address(0)); \
BUG(); \
} while (0)

View File

@ -30,9 +30,12 @@
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include "drm_crtc_internal.h"
#include "drm_internal.h"
#include <linux/component.h>
#include <linux/phy/phy.h>
#include <video/videomode.h>
#include <lx_emul/extern_c_end.h>
#include <lx_kit/scheduler.h> /* dependency of lx_emul/impl/completion.h */
@ -52,8 +55,7 @@
#include <lx_kit/irq.h>
#include <lx_kit/malloc.h>
enum Device_id { DCSS, HDMI, UNKNOWN };
enum Device_id { DCSS, HDMI, MIPI, SRC, UNKNOWN };
namespace Lx_kit {
Platform::Connection & platform_connection();
@ -84,6 +86,24 @@ Platform::Device_client & Lx_kit::platform_device(Device_id id)
return hdmi;
}
if (id == MIPI) {
static Platform::Device_client mipi {
platform_connection().device_by_property("compatible",
"fsl,imx8mq-mipi-dsi_drm") };
static bool update = true;
if (update) {
platform_connection().update();
update = false;
}
return mipi;
}
if (id == SRC){
static Platform::Device_client src {
platform_connection().acquire_device("src") };
return src;
}
throw 1;
}
@ -151,6 +171,9 @@ struct resource *platform_get_resource_byname(struct platform_device *dev,
return r;
}
if (DEBUG_DRIVER)
Genode::error("RESOURCE: ", name, " not found");
return NULL;
}
@ -160,7 +183,6 @@ static int platform_match(struct device *dev, struct device_driver *drv)
if (!dev->name)
return 0;
printk("MATCH %s %s\n", dev->name, drv->name);
return (Genode::strcmp(dev->name, drv->name) == 0);
}
@ -220,7 +242,9 @@ int platform_device_add_data(struct platform_device *pdev, const void *data,
int platform_device_register(struct platform_device *pdev)
{
pdev->dev.bus = &platform_bus_type;
if (pdev->dev.bus == nullptr)
pdev->dev.bus = &platform_bus_type;
pdev->dev.name = pdev->name;
/*Set parent to ourselfs */
if (!pdev->dev.parent)
@ -273,12 +297,20 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (DEBUG_DRIVER)
Genode::warning(__func__, "() not implemented");
if (!clk) return -1;
clk->rate = rate;
return 0;
}
int clk_prepare_enable(struct clk *clk)
{
TRACE;
return 0;
}
/******************************
** drivers/clk/clk-devres.c **
******************************/
@ -291,6 +323,7 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
const char * clock_name = id;
if (String<32>("ipg") == id) { clock_name = "apb"; }
if (String<32>("tx_esc") == id) { clock_name = "rx_esc"; }
unsigned long rate = 0;
Lx_kit::platform_connection().with_xml([&] (Xml_node node) {
@ -303,11 +336,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
});
});
if (!rate) return nullptr;
if (!rate) {
if (DEBUG_DRIVER)
Genode::error(__func__, " clock not found ", id);
return nullptr;
}
struct clk * clock = (struct clk*) kzalloc(sizeof(struct clk), GFP_KERNEL);
clock->name = id;
clock->rate = rate;
if (String<32>("tx_esc") == id)
clock->rate /= 4;
return clock;
}
@ -399,7 +440,24 @@ static struct device_node endpoint_device_node {
static struct device_node port_device_node {
.name = "port",
.full_name = "port"
.full_name = "port",
};
static struct device_node mipi_endpoint_device_node {
.name = "mipi-endpoint",
.full_name = "mipi-endpoint",
.parent = &root_device_node
};
static struct device_node mipi_device_node {
.name = "mipi_dsi",
.full_name = "mipi_dsi",
.parent = &root_device_node
};
static struct device_node mipi_panel_node {
.name = "panel",
.full_name = "panel"
};
int of_device_is_compatible(const struct device_node *device,
@ -418,16 +476,58 @@ struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev)
{
if (Genode::strcmp(node->name, "port", strlen(node->name)) == 0) {
if (!prev)
return &hdmi_endpoint_device_node;
return NULL;
if (prev)
return NULL;
if (port_device_node.parent == &mipi_device_node) {
return &port_device_node;
}
return &hdmi_endpoint_device_node;
}
Genode::error("of_get_next_child(): unhandled node");
if (Genode::strcmp(node->name, "mipi_dsi_bridge") == 0) {
if (prev) return NULL;
/* create panel device node */
device_node *np = &mipi_panel_node;
np->properties = (property *)kzalloc(6*sizeof(property), 0);
np->properties[0].name = "panel",
np->properties[0].value = NULL,
np->properties[0].next = &np->properties[1];
np->properties[1].name = "reg";
np->properties[1].value = 0;
np->properties[1].next = &np->properties[2];
np->properties[2].name = "compatible";
np->properties[2].value = (void *)"raydium,rm67191";
np->properties[2].next = &np->properties[3];
np->properties[3].name = "dsi-lanes";
np->properties[3].value = (void *)4;
np->properties[3].next = &np->properties[4];
np->properties[4].name = "panel-width-mm";
np->properties[4].value = (void *)68;
np->properties[4].next = &np->properties[5];
np->properties[5].name = "panel-height-mm";
np->properties[5].value = (void *)121;
return np;
}
if (DEBUG_DRIVER)
Genode::error("of_get_next_child(): unhandled node");
return NULL;
}
struct device_node *of_get_child_by_name(const struct device_node *node,
const char *name)
{
if (Genode::strcmp(name, "display-timings") == 0)
return (device_node *)1;
return nullptr;
}
struct device_node *of_get_parent(const struct device_node *node)
{
static device_node dcss_device_node { "dcss", "dcss" };
@ -437,21 +537,37 @@ struct device_node *of_get_parent(const struct device_node *node)
if (Genode::strcmp(node->name, "port", strlen("port")) == 0)
return &dcss_device_node;
Genode::error("of_get_parent(): unhandled node");
if (DEBUG_DRIVER)
Genode::error("of_get_parent(): unhandled node");
return NULL;
}
const void *of_get_property(const struct device_node *node, const char *name, int *lenp)
{
for (property * p = node ? node->properties : nullptr; p; p = p->next)
if (Genode::strcmp(name, p->name) == 0) return p->value;
*lenp = 0;
for (property * p = node ? node->properties : nullptr; p; p = p->next) {
if (!p) break;
if (Genode::strcmp(name, p->name) == 0) {
*lenp = sizeof(void *);
return p->value;
}
}
if (DEBUG_DRIVER) Genode::warning("OF property ", name, " not found");
if (DEBUG_DRIVER)
Genode::warning("OF property ", name, " not found");
return nullptr;
}
int of_alias_get_id(struct device_node *np, const char *stem)
{
int len = 0;
return (long)of_get_property(np, stem, &len);
}
struct device_node *of_parse_phandle(const struct device_node *np, const char *phandle_name, int index)
{
/* device node information from fsl-imx8mq.dtsi */
@ -478,6 +594,50 @@ struct device_node *of_parse_phandle(const struct device_node *np, const char *p
}
struct property *of_find_property(const struct device_node *np,
const char *name, int *lenp)
{
TRACE;
return np->properties;
}
int of_modalias_node(struct device_node *node, char *modalias, int len)
{
TRACE;
return 0;
}
/**************************
** linux/of_videomode.h **
**************************/
int of_get_videomode(struct device_node *np, struct videomode *vm, int index)
{
/* taken from device tree */
if (Genode::strcmp(np->name, "panel") == 0) {
vm->pixelclock = 0x7de2900;
vm->hactive = 0x438;
vm->hfront_porch = 0x14;
vm->hback_porch = 0x22;
vm->hsync_len = 0x2;
vm->vactive = 0x780;
vm->vfront_porch = 0x1e;
vm->vback_porch = 0x4;
vm->vsync_len = 0x2;
vm->flags = (display_flags)0x1095;
return 0;
}
return -1;
}
/*************************
** drivers/of/device.c **
*************************/
@ -495,7 +655,8 @@ const void *of_device_get_match_data(const struct device *dev)
const struct of_device_id *of_match_device(const struct of_device_id *matches,
const struct device *dev)
{
const char * compatible = (const char*) of_get_property(dev->of_node, "compatible", 0);
int len = 0;
const char * compatible = (const char*) of_get_property(dev->of_node, "compatible", &len);
for (; matches && matches->compatible[0]; matches++) {
if (Genode::strcmp(matches->compatible, compatible) == 0)
@ -505,6 +666,15 @@ const struct of_device_id *of_match_device(const struct of_device_id *matches,
}
int of_driver_match_device(struct device *dev, const struct device_driver *drv)
{
if (of_match_device(drv->of_match_table, dev))
return 1;
return 0;
}
/***************************
** drivers/of/property.c **
***************************/
@ -520,7 +690,16 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
return nullptr;
}
Genode::error(__func__, "(): unhandled parent");
if(Genode::strcmp(parent->name, "mipi_dsi", strlen(parent->name)) == 0) {
if (!prev)
return &mipi_endpoint_device_node;
return nullptr;
}
if (DEBUG_DRIVER)
Genode::error(__func__, "(): unhandled parent '", parent->name, "'");
return nullptr;
}
@ -531,7 +710,8 @@ struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id)
(id == 0))
return &port_device_node;
Genode::error("of_graph_get_port_by_id(): unhandled parent or id\n");
if (DEBUG_DRIVER)
Genode::error("of_graph_get_port_by_id(): unhandled parent or id\n");
return NULL;
}
@ -541,7 +721,12 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
if (Genode::strcmp(node->name, "endpoint", strlen(node->name)) == 0)
return &port_device_node;
Genode::error("of_graph_get_remote_port(): unhandled node\n");
if (Genode::strcmp(node->name, "mipi-endpoint", strlen(node->name)) == 0) {
return &port_device_node;
}
if (DEBUG_DRIVER)
Genode::error("of_graph_get_remote_port(): unhandled node '", node->name, "'\n");
return NULL;
}
@ -551,7 +736,18 @@ struct device_node *of_graph_get_remote_port_parent(const struct device_node *no
if (Genode::strcmp(node->name, "hdmi-endpoint") == 0)
return &hdmi_device_node;
Genode::error("of_graph_get_remote_port_parent(): unhandled node");
if (Genode::strcmp(node->name, "mipi-endpoint") == 0) {
int len;
void const *np = of_get_property(&mipi_endpoint_device_node, "mipi_dsi_bridge_np", &len);
return (device_node *)np;
}
if (Genode::strcmp(node->name, "port") == 0)
return &mipi_device_node;
if (DEBUG_DRIVER)
Genode::error("of_graph_get_remote_port_parent(): unhandled node: ", node->name);
return NULL;
}
@ -630,7 +826,7 @@ int devm_request_threaded_irq(struct device *dev, unsigned int irq,
case IRQ_IRQSTEER: id = DCSS; break;
case IRQ_HDMI_IN: id = HDMI; break;
case IRQ_HDMI_OUT: id = HDMI; off = 1; break;
default: ;
default: Genode::error(__func__, " IRQ: ", irq, " not found");
};
Lx::Irq::irq().request_irq(Lx_kit::platform_device(id).irq(off),
@ -786,7 +982,30 @@ static void *_ioremap(phys_addr_t phys_addr, unsigned long size, int wc)
};
};
panic("Failed to request I/O memory: [%lx,%lx)",
if (phys_addr >= IOMEM_BASE_MIPI_DSI &&
(phys_addr+size-1) <= IOMEM_END_MIPI_DSI) {
/*
* Set parent of 'port' to 'mipi_dsi' in order to distinguish between HDMI
* and MIPI
*/
port_device_node.parent = &mipi_device_node;
static Attached_dataspace ds {
rm, Lx_kit::platform_device(MIPI).io_mem_dataspace(0) };
addr_t off = phys_addr - IOMEM_BASE_MIPI_DSI;
return (void*)(((addr_t)ds.local_addr<void>()) + off);
}
if (phys_addr >= IOMEM_BASE_SRC &&
(phys_addr+size-1) <= IOMEM_END_SRC) {
static Attached_dataspace ds {
rm, Lx_kit::platform_device(SRC).io_mem_dataspace(0) };
return ds.local_addr<void>();
}
panic("Failed to request I/O memory: [%lx,%lx)\n",
phys_addr, phys_addr + size);
return nullptr;
}
@ -803,6 +1022,46 @@ void *devm_ioremap_resource(struct device *dev, struct resource *res)
}
/************************
** linux/mfd/syscon.h **
************************/
struct regmap *syscon_regmap_lookup_by_phandle( struct device_node *np, const char *property)
{
bool src = strcmp(property, "src") == 0;
if (!src) {
if (DEBUG_DRIVER)
Genode::warning(__func__, " property '", property, "' not found.");
return 0;
}
regmap *map = (regmap *)kzalloc(sizeof(regmap), GFP_KERNEL);
map->base = (u8 *)_ioremap(IOMEM_BASE_SRC, 0x10000, 0);
return map;
}
/********************
** linux/regmap.h **
********************/
int regmap_update_bits(struct regmap *map, unsigned reg, unsigned mask,
unsigned val)
{
if (map == nullptr) return 0;
unsigned volatile current = *((unsigned *)(map->base + reg));
current &= ~mask;
current |= val;
*((volatile unsigned *)(map->base + reg)) = current;
return 0;
}
/******************
** lib/string.c **
******************/
@ -832,7 +1091,7 @@ void reinit_completion(struct completion *work)
*/
class Driver : public Genode::List<Driver>::Element
{
private:
public:
struct device_driver *_drv; /* Linux driver */
@ -897,17 +1156,36 @@ int device_add(struct device *dev)
return 0;
/* foreach driver match and probe device */
for (Driver *driver = Driver::list()->first(); driver; driver = driver->next())
for (Driver *driver = Driver::list()->first(); driver; driver = driver->next()) {
if (driver->match(dev)) {
int ret = driver->probe(dev);
if (!ret) return 0;
}
}
return 0;
}
static bus_type *_bus = nullptr;
int bus_register(struct bus_type *bus)
{
if (_bus) {
Genode::error(__func__, " called twice, implement list");
return -ENOMEM;
}
_bus = bus;
return 0;
}
void *devm_kcalloc(struct device * /* dev */, size_t n, size_t size, gfp_t flags)
{
return kcalloc(n, size, flags);
}
/*************************
** linux/dma-mapping.h **
@ -974,7 +1252,8 @@ int devm_request_irq(struct device *dev, unsigned int irq,
case IRQ_IRQSTEER: id = DCSS; break;
case IRQ_HDMI_IN: id = HDMI; break;
case IRQ_HDMI_OUT: id = HDMI; off = 1; break;
default: ;
case IRQ_MIPI_DSI: id = MIPI; break;
default: Genode::error(__func__, " IRQ: ", irq, " not found");
};
Lx::Irq::irq().request_irq(Lx_kit::platform_device(id).irq(off),
irq, handler, dev_id);
@ -1008,14 +1287,41 @@ bool of_property_read_bool(const struct device_node *np, const char *propname)
(Genode::strcmp(propname, "fsl,no_edid", strlen(np->name)) == 0))
return false;
Genode::error(__func__, "(): unhandled property '", propname,
"' of device '", Genode::Cstring(np->name), "'");
if (DEBUG_DRIVER)
Genode::error(__func__, "(): hdmi unhandled property '", propname,
"' of device '", Genode::Cstring(np->name), "'");
return false;
}
Genode::error(__func__, "(): unhandled device '", Genode::Cstring(np->name),
"' (property: '", Genode::Cstring(propname), "')");
if ((Genode::strcmp(np->name, "mipi_dsi_bridge") == 0)) {
if (Genode::strcmp(propname, "no_clk_reset") == 0) {
/* set np in bridge endpoint */
mipi_endpoint_device_node.properties = (property*)kzalloc(sizeof(property), 0);
mipi_endpoint_device_node.properties->name = "mipi_dsi_bridge_np";
mipi_endpoint_device_node.properties->value = (void *)np;
return true;
}
if (DEBUG_DRIVER)
Genode::error(__func__, "(): mipi_dsi_bridge unhandled property '", propname,
"' of device '", Genode::Cstring(np->name), "'");
return false;
}
if (Genode::strcmp(np->name, "mipi_dsi") == 0) {
if (Genode::strcmp(propname, "no_clk_reset") == 0)
return true;
if (DEBUG_DRIVER)
Genode::error(__func__, "(): mipi_dsi unhandled property '", propname,
"' of device '", Genode::Cstring(np->name), "'");
return false;
}
if (DEBUG_DRIVER)
Genode::error(__func__, "(): unhandled device '", Genode::Cstring(np->name),
"' (property: '", Genode::Cstring(propname), "')");
return false;
}
@ -1030,13 +1336,15 @@ int of_property_read_string(const struct device_node *np, const char *propname,
return 0;
}
Genode::error(__func__, "(): unhandled property '", propname,
"' of device '", Genode::Cstring(np->name), "'");
if (DEBUG_DRIVER)
Genode::error(__func__, "(): unhandled property '", propname,
"' of device '", Genode::Cstring(np->name), "'");
return -1;
}
Genode::error(__func__, "(): unhandled device '", Genode::Cstring(np->name),
"' (property: '", Genode::Cstring(propname), "')");
if (DEBUG_DRIVER)
Genode::error(__func__, "(): unhandled device '", Genode::Cstring(np->name),
"' (property: '", Genode::Cstring(propname), "')");
return -1;
}
@ -1056,8 +1364,9 @@ int of_property_read_u32(const struct device_node *np, const char *propname, u32
return 0;
}
Genode::error(__func__, "(): unhandled property '", propname,
"' of device '", Genode::Cstring(np->name), "'");
if (DEBUG_DRIVER)
Genode::error(__func__, "(): unhandled property '", propname,
"' of device '", Genode::Cstring(np->name), "'");
return -1;
} else if (Genode::strcmp(np->name, "hdmi", strlen(np->name)) == 0) {
@ -1067,13 +1376,23 @@ int of_property_read_u32(const struct device_node *np, const char *propname, u32
return -1;
}
Genode::error(__func__, "(): unhandled property '", propname,
"' of device '", Genode::Cstring(np->name), "'");
if (DEBUG_DRIVER)
Genode::error(__func__, "(): unhandled property '", propname,
"' of device '", Genode::Cstring(np->name), "'");
return -1;
}
Genode::error(__func__, "(): unhandled device '", Genode::Cstring(np->name),
"' (property: '", Genode::Cstring(propname), "')");
int len = 0;
void const *value = of_get_property(np, propname, &len);
if (len > 0) {
*out_value = (unsigned long)value;
return 0;
}
if (DEBUG_DRIVER)
Genode::error(__func__, "(): unhandled device '", Genode::Cstring(np->name),
"' (property: '", Genode::Cstring(propname), "')");
return -1;
}
@ -1310,7 +1629,6 @@ void Framebuffer::Driver::generate_report()
xml.attribute("connected", connected);
if (!connected) return;
struct drm_display_mode *mode;
list_for_each_entry(mode, &c->modes, head) {
xml.node("mode", [&] ()
@ -1722,6 +2040,172 @@ unsigned int kref_read(const struct kref *kref)
}
/****************************
** drivers/phy/phy-core.c **
****************************/
void devm_phy_consume(struct device *dev, void *res)
{
TRACE;
}
struct phy_ops;
struct phy *devm_phy_create(struct device *dev,
struct device_node *node,
const struct phy_ops *ops)
{
TRACE;
phy **ptr = (phy**)devres_alloc(devm_phy_consume, sizeof(*ptr), GFP_KERNEL);
phy *p = (phy *)kzalloc(sizeof(phy), GFP_KERNEL);
p->dev.of_node = node;
p->ops = ops;
p->dev.parent = dev;
*ptr = p;
devres_add(dev, ptr);
return p;
}
struct phy *devm_phy_get(struct device *dev, const char *string)
{
int len = 0;
void const *phy = of_get_property(dev->of_node, string, &len);
return (struct phy *)phy;
}
int phy_init(struct phy *phy)
{
TRACE;
if (phy && phy->ops->init) {
int ret = phy->ops->init(phy);
if (ret)
Genode::error(__func__, " failed (err: ", ret, ")");
return ret;
}
return 0;
}
int phy_power_on(struct phy *phy)
{
TRACE;
if (phy && phy->ops->power_on) {
int ret = phy->ops->power_on(phy);
if (ret)
Genode::error(__func__, " failed (err: ", ret, ")");
return ret;
}
return 0;
}
/***********************
** linux/backlight.h **
***********************/
struct backlight_device *
devm_backlight_device_register(struct device *dev, const char *name,
struct device *parent, void *devdata,
const struct backlight_ops *ops,
const struct backlight_properties *props)
{
TRACE;
backlight_device *backlight = (backlight_device *)kzalloc(sizeof(backlight_device), GFP_KERNEL);
backlight->ops = ops;
backlight->props = *props;
dev_set_drvdata(&backlight->dev, devdata);
return backlight;
}
int backlight_enable(struct backlight_device *bd)
{
int ret = -ENOENT;
if (bd->ops && bd->ops->update_status)
ret = bd->ops->update_status(bd);
return ret;
}
void *bl_get_data(struct backlight_device *bl_dev)
{
return dev_get_drvdata(&bl_dev->dev);
}
/*********************
** drm/drm_panel.h **
*********************/
int drm_panel_add(struct drm_panel *panel)
{
device_node *np = &mipi_panel_node;
if (Genode::strcmp(np->properties[0].name, "panel") != 0) {
Genode::error("panel property not found");
return -1;
}
np->properties[0].value = (void*)panel;
return 0;
}
int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
{
if (panel->connector)
return -EBUSY;
panel->connector = connector;
panel->drm = connector->dev;
return 0;
}
struct drm_panel *of_drm_find_panel(const struct device_node *np)
{
int len;
return (drm_panel *)of_get_property(np, "panel", &len);
}
/***************************
** linux/gpio/consumer.h **
***************************/
struct gpio_desc *
devm_gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags)
{
TRACE;
return (struct gpio_desc *)-EINVAL;
}
void gpiod_set_value(struct gpio_desc *desc, int value)
{
TRACE;
}
/**************************************
** Stubs for non-ported driver code **
**************************************/

View File

@ -40,6 +40,11 @@ extern "C" int module_imx_drm_pdrv_init();
extern "C" int module_dcss_driver_init();
extern "C" int module_dcss_crtc_driver_init();
extern "C" int module_imx_hdp_imx_platform_driver_init();
extern "C" int module_mixel_mipi_phy_driver_init();
extern "C" int module_imx_nwl_dsi_driver_bridge_init();
extern "C" int module_imx_nwl_dsi_driver_init();
extern "C" int module_rad_panel_driver_init();
extern "C" void postcore_mipi_dsi_bus_init();
unsigned long jiffies;
@ -79,6 +84,32 @@ struct Framebuffer::Main
Lx::scheduler().schedule();
}
bool _hdmi()
{
try {
Xml_node config = _config.xml();
Xml_node xn = config.sub_node();
for (unsigned i = 0; i < config.num_sub_nodes(); xn = xn.next()) {
if (!xn.has_type("connector"))
continue;
bool enabled = xn.attribute_value("enabled", true);
if (!enabled)
continue;
/* check first connector only */
typedef String<64> Name;
Name const con_policy = xn.attribute_value("name", Name());
if (con_policy == "DSI-1")
return false;
return true;
}
} catch (...) { }
return true;
}
Main(Env &env) : _env(env)
{
log("--- i.MX8 framebuffer driver ---");
@ -88,6 +119,7 @@ struct Framebuffer::Main
LX_MUTEX_INIT(bridge_lock);
LX_MUTEX_INIT(core_lock);
LX_MUTEX_INIT(component_mutex);
LX_MUTEX_INIT(host_lock);
/* init singleton Lx::Scheduler */
Lx::scheduler(&_env);
@ -125,6 +157,13 @@ void Framebuffer::Main::_run_linux()
module_dcss_crtc_driver_init();
module_imx_hdp_imx_platform_driver_init();
/* MIPI DSI */
module_mixel_mipi_phy_driver_init();
module_imx_nwl_dsi_driver_bridge_init();
module_imx_nwl_dsi_driver_init();
postcore_mipi_dsi_bus_init();
module_rad_panel_driver_init();
/**
* This device is originally created with the name '32e2d000.irqsteer'
* via 'of_platform_bus_create()'. Here it is called 'imx-irqsteer' to match
@ -150,40 +189,6 @@ void Framebuffer::Main::_run_linux()
platform_device_register(imx_irqsteer_pdev);
/**
* This device is originally created with the name '32e00000.dcss'
* via 'of_platform_bus_create()'. Here it is called 'dcss-core' to match
* the driver name.
*/
struct platform_device *dcss_pdev =
platform_device_alloc("dcss-core", 0);
static resource dcss_resources[] = {
{ IOMEM_BASE_DCSS, IOMEM_END_DCSS, "dcss", IORESOURCE_MEM },
{ 3, 3, "dpr_dc_ch0", IORESOURCE_IRQ },
{ 4, 4, "dpr_dc_ch1", IORESOURCE_IRQ },
{ 5, 5, "dpr_dc_ch2", IORESOURCE_IRQ },
{ 6, 6, "ctx_ld", IORESOURCE_IRQ },
{ 8, 8, "ctxld_kick", IORESOURCE_IRQ },
{ 9, 9, "dtg_prg1", IORESOURCE_IRQ },
{ 16, 16, "dtrc_ch1", IORESOURCE_IRQ },
{ 17, 17, "dtrc_ch2", IORESOURCE_IRQ },
};
dcss_pdev->num_resources = 9;
dcss_pdev->resource = dcss_resources;
dcss_pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0);
dcss_pdev->dev.of_node->name = "dcss";
dcss_pdev->dev.of_node->full_name = "dcss";
dcss_pdev->dev.of_node->properties = (property*)kzalloc(sizeof(property), 0);
dcss_pdev->dev.of_node->properties->name = "disp-dev";
dcss_pdev->dev.of_node->properties->value = (void*)"hdmi_disp";
platform_device_register(dcss_pdev);
/**
* This device is originally created with the name '32c00000.hdmi'
* via 'of_platform_bus_create()'. Here it is called 'i.mx8-hdp' to match
@ -214,9 +219,90 @@ void Framebuffer::Main::_run_linux()
hdp_pdev->dev.of_node->properties->name = "compatible";
hdp_pdev->dev.of_node->properties->value = (void*)"fsl,imx8mq-hdmi";
platform_device_register(hdp_pdev);
bool hdmi = _hdmi();
if (hdmi)
platform_device_register(hdp_pdev);
struct platform_device *mipi_dsi_phy_pdev =
platform_device_alloc("mixel-mipi-dsi-phy", 0);
static resource mipi_dsi_phy_resources[] = {
{ IOMEM_BASE_MIPI_DPHY, IOMEM_BASE_MIPI_DPHY+0xff, "dsi_phy", IORESOURCE_MEM }
};
mipi_dsi_phy_pdev->num_resources = 1;
mipi_dsi_phy_pdev->resource = mipi_dsi_phy_resources;
mipi_dsi_phy_pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0);
mipi_dsi_phy_pdev->dev.of_node->properties = (property*)kzalloc(2*sizeof(property), 0);
mipi_dsi_phy_pdev->dev.of_node->properties[0].name = "compatible";
mipi_dsi_phy_pdev->dev.of_node->properties[0].value = (void*)"mixel,imx8mq-mipi-dsi-phy";
mipi_dsi_phy_pdev->dev.of_node->properties[0].next = &mipi_dsi_phy_pdev->dev.of_node->properties[1];
mipi_dsi_phy_pdev->dev.of_node->properties[1].name = "dsi_phy";
mipi_dsi_phy_pdev->dev.of_node->properties[1].value = (void*)0;
mipi_dsi_phy_pdev->dev.parent = &mipi_dsi_phy_pdev->dev;
if (hdmi == false) {
platform_device_register(mipi_dsi_phy_pdev);
}
/**
* This device is originally created with the name '32e00000.dcss'
* via 'of_platform_bus_create()'. Here it is called 'dcss-core' to match
* the driver name.
*/
struct platform_device *dcss_pdev =
platform_device_alloc("dcss-core", 0);
static resource dcss_resources[] = {
{ IOMEM_BASE_DCSS, IOMEM_END_DCSS, "dcss", IORESOURCE_MEM },
{ 3, 3, "dpr_dc_ch0", IORESOURCE_IRQ },
{ 4, 4, "dpr_dc_ch1", IORESOURCE_IRQ },
{ 5, 5, "dpr_dc_ch2", IORESOURCE_IRQ },
{ 6, 6, "ctx_ld", IORESOURCE_IRQ },
{ 8, 8, "ctxld_kick", IORESOURCE_IRQ },
{ 9, 9, "dtg_prg1", IORESOURCE_IRQ },
{ 16, 16, "dtrc_ch1", IORESOURCE_IRQ },
{ 17, 17, "dtrc_ch2", IORESOURCE_IRQ },
};
dcss_pdev->num_resources = 9;
dcss_pdev->resource = dcss_resources;
dcss_pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0);
dcss_pdev->dev.of_node->name = "dcss";
dcss_pdev->dev.of_node->full_name = "dcss";
dcss_pdev->dev.of_node->properties = (property*)kzalloc(sizeof(property), 0);
dcss_pdev->dev.of_node->properties->name = "disp-dev";
dcss_pdev->dev.of_node->properties->value = hdmi ? (void*)"hdmi_disp" : (void *)"mipi_disp";
platform_device_register(dcss_pdev);
struct platform_device *mipi_dsi_bridge_pdev =
platform_device_alloc("nwl-mipi-dsi", 0);
static resource mipi_dsi_bridge_resources[] = {
{ IOMEM_BASE_MIPI_DSI, IOMEM_END_MIPI_DSI, "mipi_dsi_bridge", IORESOURCE_MEM },
{ IRQ_MIPI_DSI, IRQ_MIPI_DSI, "mipi_dsi", IORESOURCE_IRQ }
};
mipi_dsi_bridge_pdev->num_resources = 2;
mipi_dsi_bridge_pdev->resource = mipi_dsi_bridge_resources;
Genode::addr_t **phy_ptr =
(Genode::addr_t **)devres_find(&mipi_dsi_phy_pdev->dev, devm_phy_consume, nullptr, nullptr);
mipi_dsi_bridge_pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0);
mipi_dsi_bridge_pdev->dev.of_node->name = "mipi_dsi_bridge";
mipi_dsi_bridge_pdev->dev.of_node->properties = (property*)kzalloc(sizeof(property), 0);
mipi_dsi_bridge_pdev->dev.of_node->properties[0].name = "dphy";
mipi_dsi_bridge_pdev->dev.of_node->properties[0].value = phy_ptr ? (void*)*phy_ptr : nullptr;
mipi_dsi_bridge_pdev->dev.of_node->properties[0].next = nullptr;
if (hdmi == false)
platform_device_register(mipi_dsi_bridge_pdev);
/*
* This device is originally created with the name 'display-subsystem'
* via 'of_platform_bus_create()'. Here it is called 'imx-drm' to match
* the driver name.
@ -231,6 +317,20 @@ void Framebuffer::Main::_run_linux()
platform_device_register(display_subsystem_pdev);
struct platform_device *mipi_dsi_imx_pdev =
platform_device_alloc("nwl_dsi-imx", 0);
mipi_dsi_imx_pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0);
mipi_dsi_imx_pdev->dev.of_node->name = "mipi_dsi";
mipi_dsi_imx_pdev->dev.of_node->properties = (property*)kzalloc(2*sizeof(property), 0);
mipi_dsi_imx_pdev->dev.of_node->properties[0].name = "compatible";
mipi_dsi_imx_pdev->dev.of_node->properties[0].value = (void *)"fsl,imx8mq-mipi-dsi_drm";
mipi_dsi_imx_pdev->dev.of_node->properties[0].next = &mipi_dsi_imx_pdev->dev.of_node->properties[1];
mipi_dsi_imx_pdev->dev.of_node->properties[1].name = "dphy";
mipi_dsi_imx_pdev->dev.of_node->properties[1].value = phy_ptr ? (void *)*phy_ptr : nullptr;
if (hdmi == false)
platform_device_register(mipi_dsi_imx_pdev);
_driver.finish_initialization();
_driver.config_sigh(_policy_change_handler);

View File

@ -78,7 +78,7 @@ static inline void panic(const char *fmt, ...)
va_start(args, fmt);
lx_vprintf(fmt, args);
va_end(args);
lx_printf("panic()");
lx_printf("\npanic()\n");
while (1) ;
}