当前位置: 首页 > news >正文

网站中文名称胶州做网站的

网站中文名称,胶州做网站的,小说网站排名免费,手机做图片的网站1.概述 手头有一块RK3568的开发板OK3568-C#xff0c;但是还没有适配OpenHarmony#xff0c;用的还是LVDS屏幕#xff0c;但是官方和网上好像还没有OpenHarmony4.0的LVDS屏幕驱动的通用实现#xff0c;所以决定尝试了一下适配该开发板#xff0c;完成LVDS屏幕驱动的适配但是还没有适配OpenHarmony用的还是LVDS屏幕但是官方和网上好像还没有OpenHarmony4.0的LVDS屏幕驱动的通用实现所以决定尝试了一下适配该开发板完成LVDS屏幕驱动的适配点亮屏幕。 源代码oh4.0-lvds-ok3568-c 2.具体实现 2.1 添加ok3568产品非必须可以跳过直接修改原有的rk3568产品 因为OK3568-C开发板使用的是RK3568芯片和OpenHarmony的主线分支一样所以添加ok3568产品的基础流程比较简单就是复制device和vendor下面rk3568的文件夹改为ok3568并加入ok3568对应的设备树文件修改build文件下面的编译配置文件不修改编译会报错具体流程可以参考官方和网上的其他教程。 本次使用的LVDS屏幕对应的设备树节点如下 OK3568-common.dtsi 2.2 分析原有的MIPI屏幕驱动 参考鸿蒙系统原有的MIPI屏幕驱动目录drivers/framework/model/display/driver下面的ili9881_st_5p5.c和hdf_drm_panel.c 可以看出鸿蒙原有的MIPI屏幕驱动实际上参考了Linux内核的drivers/gpu/drm/panel/panel-simple.c的“simple-panel-dsi”部分不知道为什么官方没有把panel-simple.c中剩下的“simple-panel”部分加进去。而“simple-panel”剩余的部分就是LVDS和EDP这类屏幕通用的驱动。 2.3 实现LVDS屏幕驱动 这里我们也参考Linux内核的drivers/gpu/drm/panel/panel-simple.c 2.3.1 读取设备树里面的simple-panel节点获取Panel的参数 添加如下两个文件 panel_simple_common.h /*** HDF is dual licensed: you can use it either under the terms of* the GPL, or the BSD license, at your option.* See the LICENSE file in the root of this repository for complete details.*/#ifndef PANEL_SIMPLE_COMMON_H #define PANEL_SIMPLE_COMMON_H#include linux/backlight.h #include linux/of.h #include linux/of_platform.h #include linux/regulator/consumer.h #include linux/gpio/consumer.h#include video/display_timing.h #include video/mipi_display.h #include video/of_display_timing.h #include video/videomode.h#include drm/drm_modes.h #include drm/drm_panel.h#include uapi/drm/drm_mode.h#include securec.h#include hdf_disp.h #include hdf_drm_panel_simple.h#endif /* PANEL_SIMPLE_COMMON_H */panel_simple_common.c /*** HDF is dual licensed: you can use it either under the terms of* the GPL, or the BSD license, at your option.* See the LICENSE file in the root of this repository for complete details.*/#include panel_simple_common.h #include gpio_if.h #include hdf_bl.h #include hdf_disp.h #include osal.hstatic inline struct panel_simple *to_panel_simple(const struct drm_panel *panel) {return container_of(panel, struct panel_simple, panel); }static inline struct panel_simple *to_panel_simple_by_data(const struct PanelData *panel_data) {return container_of(panel_data, struct panel_simple, panel_data); }static int panel_simple_parse_cmd_seq(struct device *dev,const u8 *data, int length,struct panel_cmd_seq *seq) {struct panel_cmd_header *header;struct panel_cmd_desc *desc;char *buf, *d;unsigned int i, cnt, len;if (!seq)return -EINVAL;buf (u8 *)OsalMemCalloc(length);if (!buf)return -ENOMEM;memcpy_s(buf, length, data, length);d buf;len length;cnt 0;while (len sizeof(*header)) {header (struct panel_cmd_header *)d;d sizeof(*header);len - sizeof(*header);if (header-payload_length len)return -EINVAL;d header-payload_length;len - header-payload_length;cnt;}if (len)return -EINVAL;seq-cmd_cnt cnt;seq-cmds (struct panel_cmd_desc *)OsalMemCalloc(sizeof(*desc));if (!seq-cmds)return -ENOMEM;d buf;len length;for (i 0; i cnt; i) {header (struct panel_cmd_header *)d;len - sizeof(*header);d sizeof(*header);desc seq-cmds[i];desc-header *header;desc-payload d;d header-payload_length;len - header-payload_length;}return 0; }static int32_t panel_simple_regulator_enable(struct panel_simple *p) {int32_t err;if (p-power_invert) {if (regulator_is_enabled(p-supply) 0)regulator_disable(p-supply);} else {err regulator_enable(p-supply);if (err 0)return err;}return 0; }static int32_t panel_simple_regulator_disable(struct panel_simple *p) {int err;if (p-power_invert) {if (!regulator_is_enabled(p-supply)) {err regulator_enable(p-supply);if (err 0)return err;}} else {regulator_disable(p-supply);}return 0; }int panel_simple_loader_protect(struct drm_panel *panel) {struct panel_simple *p to_panel_simple(panel);int err;err panel_simple_regulator_enable(p);if (err 0) {HDF_LOGE(failed to enable supply: %d\n, err);return err;}p-prepared true;p-enabled true;return 0; } EXPORT_SYMBOL(panel_simple_loader_protect);static int panel_simple_get_hpd_gpio(struct device *dev,struct panel_simple *p, bool from_probe) {int err;p-hpd_gpio devm_gpiod_get_optional(dev, hpd, GPIOD_IN);if (IS_ERR(p-hpd_gpio)) {err PTR_ERR(p-hpd_gpio);/** If were called from probe we wont consider -EPROBE_DEFER* to be an error--well leave the error code in hpd_gpio.* When we try to use it well try again. This allows for* circular dependencies where the component providing the* hpd gpio needs the panel to init before probing.*/if (err ! -EPROBE_DEFER || !from_probe) {HDF_LOGE(failed to get hpd GPIO: %d\n, err);return err;}}return 0; }#define PANEL_SIMPLE_BOUNDS_CHECK(to_check, bounds, field) \(to_check-field.typ bounds-field.min \to_check-field.typ bounds-field.max) static void panel_simple_parse_panel_timing_node(struct device *dev,struct panel_simple *panel,const struct display_timing *ot) {const struct panel_desc *desc panel-desc;struct videomode vm;unsigned int i;if (WARN_ON(desc-num_modes)) {HDF_LOGE(Reject override mode: panel has a fixed mode\n);return;}if (WARN_ON(!desc-num_timings)) {HDF_LOGE(Reject override mode: no timings specified\n);return;}for (i 0; i panel-desc-num_timings; i) {const struct display_timing *dt panel-desc-timings[i];if (!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hactive) ||!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hfront_porch) ||!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hback_porch) ||!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hsync_len) ||!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vactive) ||!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vfront_porch) ||!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vback_porch) ||!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vsync_len))continue;if (ot-flags ! dt-flags)continue;videomode_from_timing(ot, vm);drm_display_mode_from_videomode(vm, panel-override_mode);panel-override_mode.type | DRM_MODE_TYPE_DRIVER |DRM_MODE_TYPE_PREFERRED;break;}if (WARN_ON(!panel-override_mode.type))HDF_LOGE(Reject override mode: No display_timing found\n); }static int32_t PanelOn(struct PanelData *data) {struct panel_simple *p to_panel_simple_by_data(data);if (p-enabled)return HDF_SUCCESS;if (p-desc-delay.enable)OsalMSleep(p-desc-delay.enable);p-enabled true;return HDF_SUCCESS; }static int32_t PanelOff(struct PanelData *data) {struct panel_simple *simplePanel NULL;simplePanel to_panel_simple_by_data(data);if (simplePanel-desc-delay.disable) {OsalMSleep(simplePanel-desc-delay.disable);}return HDF_SUCCESS; }static int32_t PanelPrepare(struct PanelData *data) {struct panel_simple *p to_panel_simple_by_data(data);unsigned int delay;int err;int hpd_asserted;if (p-prepared)return HDF_SUCCESS;err panel_simple_regulator_enable(p);if (err 0) {HDF_LOGE(failed to enable supply: %d\n, err);return err;}gpiod_direction_output(p-enable_gpio, 1);if (p-desc-delay.reset)OsalMSleep(p-desc-delay.reset);gpiod_direction_output(p-reset_gpio, 1);if (p-desc-delay.reset)OsalMSleep(p-desc-delay.reset);gpiod_direction_output(p-reset_gpio, 0);delay p-desc-delay.prepare;if (p-no_hpd)delay p-desc-delay.hpd_absent_delay;if (delay)OsalMSleep(delay);// if (p-hpd_gpio) {// if (IS_ERR(p-hpd_gpio)) {// err panel_simple_get_hpd_gpio(panel-dev, p, false);// if (err)// return err;// }// err readx_poll_timeout(gpiod_get_value_cansleep, p-hpd_gpio,// hpd_asserted, hpd_asserted,// 1000, 2000000);// if (hpd_asserted 0)// err hpd_asserted;// if (err) {// HDF_LOGE(error waiting for hpd GPIO: %d\n, err);// return err;// }// }// if (p-desc-init_seq)// if (p-dsi)// panel_simple_xfer_dsi_cmd_seq(p, p-desc-init_seq);if (p-desc-delay.init)OsalMSleep(p-desc-delay.init);p-prepared true;return HDF_SUCCESS; }static int32_t PanelUnprepare(struct PanelData *data) {int32_t ret;struct panel_simple *p NULL;p to_panel_simple_by_data(data);if (!p-prepared)return HDF_SUCCESS;gpiod_direction_output(p-reset_gpio, 1);gpiod_direction_output(p-enable_gpio, 0);panel_simple_regulator_disable(p);if (p-desc-delay.unprepare) {OsalMSleep(p-desc-delay.unprepare);}return HDF_SUCCESS; }static int32_t PanelInit(struct PanelData *panel) {return 0; }static int32_t panel_simple_probe(struct device *dev, struct panel_simple *panel) {const struct panel_desc *desc panel-desc;struct display_timing dt;int connector_type;u32 bus_flags;int32_t err;panel-no_hpd of_property_read_bool(dev-of_node, no-hpd);if (!panel-no_hpd) {err panel_simple_get_hpd_gpio(dev, panel, true);if (err){HDF_LOGE(%s Get hpd gpio fail %d, __func__, err);goto FAIL;}}panel-supply devm_regulator_get(dev, power);if (IS_ERR(panel-supply)) {HDF_LOGE(%s Get regulator fail %d, __func__, PTR_ERR(panel-supply));goto FAIL;}panel-enable_gpio devm_gpiod_get_optional(dev, enable, GPIOD_ASIS);if (IS_ERR(panel-enable_gpio)) {HDF_LOGE(%s get enable_gpio fail %d, __func__, PTR_ERR(panel-enable_gpio));goto FAIL;}panel-reset_gpio devm_gpiod_get_optional(dev, reset, GPIOD_ASIS);if (IS_ERR(panel-reset_gpio)) {HDF_LOGE(get reset_gpio fail %d, __func__, PTR_ERR(panel-reset_gpio));goto FAIL;}if (!of_get_display_timing(dev-of_node, panel-timing, dt))panel_simple_parse_panel_timing_node(dev, panel, dt);connector_type desc-connector_type;/* Catch common mistakes for panels. */switch (connector_type) {case 0:HDF_LOGD(Specify missing connector_type\n);connector_type DRM_MODE_CONNECTOR_DPI;break;case DRM_MODE_CONNECTOR_LVDS:WARN_ON(desc-bus_flags ~(DRM_BUS_FLAG_DE_LOW |DRM_BUS_FLAG_DE_HIGH |DRM_BUS_FLAG_DATA_MSB_TO_LSB |DRM_BUS_FLAG_DATA_LSB_TO_MSB));WARN_ON(desc-bus_format ! MEDIA_BUS_FMT_RGB666_1X7X3_SPWG desc-bus_format ! MEDIA_BUS_FMT_RGB888_1X7X4_SPWG desc-bus_format ! MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA);WARN_ON(desc-bus_format MEDIA_BUS_FMT_RGB666_1X7X3_SPWG desc-bpc ! 6);WARN_ON((desc-bus_format MEDIA_BUS_FMT_RGB888_1X7X4_SPWG ||desc-bus_format MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA) desc-bpc ! 8);break;case DRM_MODE_CONNECTOR_eDP:if (desc-bus_format 0)HDF_LOGW(Specify missing bus_format\n);if (desc-bpc ! 6 desc-bpc ! 8)HDF_LOGW(Expected bpc in {6,8} but got: %u\n, desc-bpc);break;case DRM_MODE_CONNECTOR_DSI:if (desc-bpc ! 6 desc-bpc ! 8)HDF_LOGW(Expected bpc in {6,8} but got: %u\n, desc-bpc);break;case DRM_MODE_CONNECTOR_DPI:bus_flags DRM_BUS_FLAG_DE_LOW |DRM_BUS_FLAG_DE_HIGH |DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE |DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |DRM_BUS_FLAG_DATA_MSB_TO_LSB |DRM_BUS_FLAG_DATA_LSB_TO_MSB |DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE |DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE;if (desc-bus_flags ~bus_flags)HDF_LOGW(Unexpected bus_flags(%d)\n, desc-bus_flags ~bus_flags);if (!(desc-bus_flags bus_flags))HDF_LOGW(Specify missing bus_flags\n);if (desc-bus_format 0)HDF_LOGW(Specify missing bus_format\n);if (desc-bpc ! 6 desc-bpc ! 8)HDF_LOGW(Expected bpc in {6,8} but got: %u\n, desc-bpc);break;default:HDF_LOGW(Specify a valid connector_type: %d\n, desc-connector_type);connector_type DRM_MODE_CONNECTOR_DPI;break;}HDF_LOGI(%s success, __func__);return HDF_SUCCESS; FAIL:return HDF_FAILURE; }static bool of_child_node_is_present(const struct device_node *node,const char *name) {struct device_node *child;child of_get_child_by_name(node, name);of_node_put(child);return !!child; }static int panel_simple_of_get_desc_data(struct device *dev,struct panel_desc *desc) {struct device_node *np dev-of_node;u32 bus_flags;const void *data;int len;int err;if (of_child_node_is_present(np, display-timings)) {struct drm_display_mode *mode;mode (struct drm_display_mode *)OsalMemCalloc(sizeof(*mode));if (!mode)return -ENOMEM;err of_get_drm_display_mode(np, mode, bus_flags,OF_USE_NATIVE_MODE);if (!err) {desc-modes mode;desc-num_modes 1;desc-bus_flags bus_flags;}} else if (of_child_node_is_present(np, panel-timing)) {struct display_timing *timing;struct videomode vm;timing (struct display_timing *)OsalMemCalloc(sizeof(*timing));if (!timing)return -ENOMEM;if (!of_get_display_timing(np, panel-timing, timing)) {desc-timings timing;desc-num_timings 1;bus_flags 0;vm.flags timing-flags;drm_bus_flags_from_videomode(vm, bus_flags);desc-bus_flags bus_flags;}}if (desc-num_modes || desc-num_timings) {of_property_read_u32(np, bpc, desc-bpc);of_property_read_u32(np, bus-format, desc-bus_format);of_property_read_u32(np, width-mm, desc-size.width);of_property_read_u32(np, height-mm, desc-size.height);}of_property_read_u32(np, prepare-delay-ms, desc-delay.prepare);of_property_read_u32(np, enable-delay-ms, desc-delay.enable);of_property_read_u32(np, disable-delay-ms, desc-delay.disable);of_property_read_u32(np, unprepare-delay-ms, desc-delay.unprepare);of_property_read_u32(np, reset-delay-ms, desc-delay.reset);of_property_read_u32(np, init-delay-ms, desc-delay.init);data of_get_property(np, panel-init-sequence, len);if (data) {desc-init_seq (struct panel_cmd_seq *)OsalMemCalloc(sizeof(*desc-init_seq));if (!desc-init_seq)return -ENOMEM;err panel_simple_parse_cmd_seq(dev, data, len,desc-init_seq);if (err) {HDF_LOGE(failed to parse init sequence\n);return err;}}data of_get_property(np, panel-exit-sequence, len);if (data) {desc-exit_seq (struct panel_cmd_seq *)OsalMemCalloc(sizeof(*desc-exit_seq));if (!desc-exit_seq)return -ENOMEM;err panel_simple_parse_cmd_seq(dev, data, len,desc-exit_seq);if (err) {HDF_LOGE(failed to parse exit sequence\n);return err;}}return 0; }#define BLK_PWM_INDEX 2 #define PWM_MAX_PERIOD 40000 /* backlight setting */ #define MIN_LEVEL 0 #define MAX_LEVEL 255 #define DEFAULT_LEVEL 127static struct PanelInfo g_panelInfo {.width 720, /* width */.height 1280, /* height */.hbp 40, /* horizontal back porch */.hfp 40, /* horizontal front porch */.hsw 10, /* horizontal sync width */.vbp 15, /* vertical back porch */.vfp 10, /* vertical front porch */.vsw 36, /* vertical sync width */.clockFreq 75000000, /* clock */.pWidth 68, /* physical width */.pHeight 121, /* physical height */.connectorType DRM_MODE_CONNECTOR_DPI, /* DRM_MODE_CONNECTOR_DPI17 */.blk { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL }, };static void PanelDataInit(struct panel_simple *panel, struct HdfDeviceObject *object) {struct PanelData *panel_data panel-panel_data;panel_data-object object;panel_data-init PanelInit;panel_data-on PanelOn;panel_data-off PanelOff;panel_data-prepare PanelPrepare;panel_data-unprepare PanelUnprepare;panel_data-info g_panelInfo;panel_data-priv panel; }static int32_t PanelEntryInit(struct HdfDeviceObject *object) {struct device_node *panelNode NULL;struct platform_device *pdev NULL;struct panel_simple *simplePanel NULL;struct panel_desc *desc NULL;int err;bool hasPanel false;HDF_LOGI(PanelEntryInit);while((panelNode of_find_compatible_node(panelNode, NULL, simple-panel)) ! NULL){hasPanel true;pdev of_find_device_by_node(panelNode);if (pdev NULL) {HDF_LOGE(%s of_find_device_by_node fail, __func__);goto FAIL;}desc (struct panel_desc *)OsalMemCalloc(sizeof(*desc));if (desc NULL) {HDF_LOGE(%s panel_desc malloc fail, __func__);goto FAIL;}err panel_simple_of_get_desc_data(pdev-dev, desc);if (err) {HDF_LOGE(%s failed to get desc data: %d\n, __func__, err);goto FAIL;}simplePanel (struct panel_simple *)OsalMemCalloc(sizeof(struct panel_simple));if (simplePanel NULL) {HDF_LOGE(%s simplePanel malloc fail, __func__);goto FAIL;}simplePanel-desc desc;simplePanel-panel.dev pdev-dev;err panel_simple_probe(pdev-dev, simplePanel);if (err) {HDF_LOGE(%s failed to panel_simple_probe: %d\n, __func__, err);goto FAIL;}PanelDataInit(simplePanel, object);if (RegisterPanel(simplePanel-panel_data) ! HDF_SUCCESS) {HDF_LOGE(RegisterPanel fail);goto FAIL;}of_node_put(panelNode);}if (!hasPanel) {HDF_LOGE(%s panel simple not found!!!, __func__);goto FAIL;}HDF_LOGI(%s success, __func__);return HDF_SUCCESS; FAIL:OsalMemFree(desc);OsalMemFree(simplePanel);of_node_put(panelNode);return HDF_FAILURE; }struct HdfDriverEntry g_commonPanelSimpleDevEntry {.moduleVersion 1,.moduleName PANEL_SIMPLE_COMMON,.Init PanelEntryInit, };HDF_INIT(g_commonPanelSimpleDevEntry);2.3.2 在DRM显示框架中注册上一步获取到的Panel对象 添加如下两个文件 hdf_drm_panel_simple.h /** Copyright (c) 2020-2021 Huawei Device Co., Ltd.** HDF is dual licensed: you can use it either under the terms of* the GPL, or the BSD license, at your option.* See the LICENSE file in the root of this repository for complete details.*/#ifndef HDF_DRM_PANEL_SIMPLE_H #define HDF_DRM_PANEL_SIMPLE_H #include linux/of_platform.h #include linux/platform_device.h#include video/display_timing.h #include video/mipi_display.h #include video/of_display_timing.h #include video/videomode.h#include drm/drm_crtc.h #include drm/drm_device.h #include drm/drm_mipi_dsi.h #include drm/drm_panel.h #include drm/drm_dsc.h#include hdf_disp.h #include hdf_bl.hstruct panel_cmd_header {u8 data_type;u8 delay;u8 payload_length; } __packed;struct panel_cmd_desc {struct panel_cmd_header header;u8 *payload; };struct panel_cmd_seq {struct panel_cmd_desc *cmds;unsigned int cmd_cnt; };/*** modes: Pointer to array of fixed modes appropriate for this panel. If* only one mode then this can just be the address of this the mode.* NOTE: cannot be used with timings and also if this is specified* then you cannot override the mode in the device tree.* num_modes: Number of elements in modes array.* timings: Pointer to array of display timings. NOTE: cannot be used with* modes and also these will be used to validate a device tree* override if one is present.* num_timings: Number of elements in timings array.* bpc: Bits per color.* size: Structure containing the physical size of this panel.* delay: Structure containing various delay values for this panel.* bus_format: See MEDIA_BUS_FMT_... defines.* bus_flags: See DRM_BUS_FLAG_... defines.*/ struct panel_desc {const struct drm_display_mode *modes;unsigned int num_modes;const struct display_timing *timings;unsigned int num_timings;unsigned int bpc;/*** width: width (in millimeters) of the panels active display area* height: height (in millimeters) of the panels active display area*/struct {unsigned int width;unsigned int height;} size;/*** prepare: the time (in milliseconds) that it takes for the panel to* become ready and start receiving video data* hpd_absent_delay: Add this to the prepare delay if we know Hot* Plug Detect isnt used.* enable: the time (in milliseconds) that it takes for the panel to* display the first valid frame after starting to receive* video data* disable: the time (in milliseconds) that it takes for the panel to* turn the display off (no content is visible)* unprepare: the time (in milliseconds) that it takes for the panel* to power itself down completely* reset: the time (in milliseconds) that it takes for the panel* to reset itself completely* init: the time (in milliseconds) that it takes for the panel to* send init command sequence after reset deassert*/struct {unsigned int prepare;unsigned int hpd_absent_delay;unsigned int enable;unsigned int disable;unsigned int unprepare;unsigned int reset;unsigned int init;} delay;u32 bus_format;u32 bus_flags;int connector_type;struct panel_cmd_seq *init_seq;struct panel_cmd_seq *exit_seq; };struct panel_simple {struct drm_panel panel;struct mipi_dsi_device *dsi;bool prepared;bool enabled;bool power_invert;bool no_hpd;const struct panel_desc *desc;struct regulator *supply;struct gpio_desc *enable_gpio;struct gpio_desc *reset_gpio;struct gpio_desc *hpd_gpio;struct drm_display_mode override_mode;enum drm_panel_orientation orientation;struct PanelData panel_data;uint32_t index;struct DispManager *manager; };#endif /* HDF_DRM_PANEL_SIMPLE_H */ hdf_drm_panel_simple.c /*** HDF is dual licensed: you can use it either under the terms of* the GPL, or the BSD license, at your option.* See the LICENSE file in the root of this repository for complete details.*/#include hdf_drm_panel_simple.h #include drm/drm_device.h #include drm/drm_atomic_helper.h #include linux/backlight.h #include linux/module.h #include linux/of.h #include linux/of_gpio.h #include linux/pm_runtime.h #include linux/regulator/consumer.h #include video/mipi_display.h #include video/of_display_timing.h #include video/videomode.h #include uapi/drm/drm_mode.h #include osal_mem.h #include osal.hstatic inline struct panel_simple *to_panel_simple(const struct drm_panel *panel) {return container_of(panel, struct panel_simple, panel); }static int HdfDrmPanelSimpleUnprepare(struct drm_panel *panel) {struct panel_simple *simpePanel to_panel_simple(panel);struct PanelData *panelData;struct DispManager *manager GetDispManager();HDF_LOGD(HdfDrmPanelSimpleUnprepare);if (simpePanel-index PANEL_MAX) {HDF_LOGE(panel num out of PANEL_MAX);return HDF_FAILURE;}OsalMutexLock(manager-dispMutex);panelData manager-panelManager-panel[simpePanel-index];panelData-unprepare(panelData);OsalMutexUnlock(manager-dispMutex);return HDF_SUCCESS; }static int HdfDrmPanelSimplePrepare(struct drm_panel *panel) {struct panel_simple *simpePanel to_panel_simple(panel);struct PanelData *panelData;struct DispManager *manager GetDispManager();HDF_LOGD(HdfDrmPanelSimplePrepare);if (simpePanel-index PANEL_MAX) {HDF_LOGE(panel num out of PANEL_MAX);return HDF_FAILURE;}OsalMutexLock(manager-dispMutex);panelData manager-panelManager-panel[simpePanel-index];panelData-prepare(panelData);OsalMutexUnlock(manager-dispMutex);return HDF_SUCCESS; }static int HdfDrmPanelSimpleDisable(struct drm_panel *panel) {struct panel_simple *simpePanel to_panel_simple(panel);struct PanelData *panelData;struct DispManager *manager GetDispManager();HDF_LOGD(HdfDrmPanelSimpleDisable);if (simpePanel-index PANEL_MAX) {HDF_LOGE(panel num out of PANEL_MAX);return HDF_FAILURE;}OsalMutexLock(manager-dispMutex);panelData manager-panelManager-panel[simpePanel-index];panelData-off(panelData);OsalMutexUnlock(manager-dispMutex);return HDF_SUCCESS; }static int HdfDrmPanelSimpleEnable(struct drm_panel *panel) {struct panel_simple *simpePanel to_panel_simple(panel);struct PanelData *panelData;struct DispManager *manager GetDispManager();HDF_LOGD(HdfDrmPanelSimpleEnable);if (simpePanel-index PANEL_MAX) {HDF_LOGE(panel num out of PANEL_MAX);return HDF_FAILURE;}panelData manager-panelManager-panel[simpePanel-index];OsalMutexLock(manager-dispMutex);panelData-on(panelData);OsalMutexUnlock(manager-dispMutex);return HDF_SUCCESS; }#define MIN_LEVEL 0 #define MAX_LEVEL 255 #define DEFAULT_LEVEL 100static int32_t SetPanelInfo(struct panel_simple *simplePanel, struct drm_display_mode *mode) {HDF_LOGI(SetPanelInfo enter);struct PanelData *panel simplePanel-panel_data;panel-info-clockFreq mode-clock * 1000;panel-info-width mode-hdisplay;panel-info-height mode-vdisplay;panel-info-hbp mode-htotal - mode-hsync_end;panel-info-hfp mode-hsync_start - mode-hdisplay;panel-info-hsw mode-hsync_end - mode-hsync_start;panel-info-vbp mode-vtotal - mode-vsync_end;panel-info-vfp mode-vsync_start - mode-vdisplay;panel-info-vsw mode-vsync_end - mode-vsync_start;// panel-info-intfType LCD_24BIT;// panel-info-intfSync 0;// panel-info-frameRate 0;panel-info-blk.type BLK_PWM;panel-info-blk.minLevel MIN_LEVEL;panel-info-blk.maxLevel MAX_LEVEL;panel-info-blk.defLevel DEFAULT_LEVEL;return HDF_SUCCESS; }static unsigned int panel_simple_get_timings_modes(struct panel_simple *panel,struct drm_connector *connector) {struct drm_display_mode *mode;unsigned int i, num 0;for (i 0; i panel-desc-num_timings; i) {const struct display_timing *dt panel-desc-timings[i];struct videomode vm;videomode_from_timing(dt, vm);mode drm_mode_create(connector-dev);if (!mode) {HDF_LOGE(failed to add mode %ux%u\n, dt-hactive.typ, dt-vactive.typ);continue;}drm_display_mode_from_videomode(vm, mode);mode-type | DRM_MODE_TYPE_DRIVER;if (panel-desc-num_timings 1)mode-type | DRM_MODE_TYPE_PREFERRED;drm_mode_probed_add(connector, mode);num;HDF_LOGI(panel_simple_get_timings_modes SetPanelInfo:%d, i);SetPanelInfo(panel, mode);}return num; }static unsigned int panel_simple_get_display_modes(struct panel_simple *panel,struct drm_connector *connector) {struct drm_display_mode *mode;unsigned int i, num 0;HDF_LOGI(panel_simple_get_display_modes enter);for (i 0; i panel-desc-num_modes; i) {const struct drm_display_mode *m panel-desc-modes[i];mode drm_mode_duplicate(connector-dev, m);if (!mode) {HDF_LOGE(failed to add mode %ux%u%u\n,m-hdisplay, m-vdisplay,drm_mode_vrefresh(m));continue;}mode-type | DRM_MODE_TYPE_DRIVER;if (panel-desc-num_modes 1)mode-type | DRM_MODE_TYPE_PREFERRED;drm_mode_set_name(mode);drm_mode_probed_add(connector, mode);num;HDF_LOGI(panel_simple_get_display_modes SetPanelInfo:%d num:%d, i, num);SetPanelInfo(panel, mode);}return num; }static int panel_simple_get_non_edid_modes(struct panel_simple *panel,struct drm_connector *connector) {struct drm_display_mode *mode;bool has_override panel-override_mode.type;unsigned int num 0;if (!panel-desc)return 0;if (has_override) {mode drm_mode_duplicate(connector-dev,panel-override_mode);if (mode) {drm_mode_probed_add(connector, mode);num 1;HDF_LOGI(panel_simple_get_non_edid_modes SetPanelInfo);SetPanelInfo(panel, mode);} else {HDF_LOGE(failed to add override mode\n);}}/* Only add timings if override was not there or failed to validate */if (num 0 panel-desc-num_timings)num panel_simple_get_timings_modes(panel, connector);/** Only add fixed modes if timings/override added no mode.** We should only ever have either the display timings specified* or a fixed mode. Anything else is rather bogus.*/WARN_ON(panel-desc-num_timings panel-desc-num_modes);if (num 0)num panel_simple_get_display_modes(panel, connector);if (panel-desc-bpc)connector-display_info.bpc panel-desc-bpc;if (panel-desc-size.width)connector-display_info.width_mm panel-desc-size.width;if (panel-desc-size.height)connector-display_info.height_mm panel-desc-size.height;if (panel-desc-bus_format)drm_display_info_set_bus_formats(connector-display_info,panel-desc-bus_format, 1);if (panel-desc-bus_flags)connector-display_info.bus_flags panel-desc-bus_flags;return num; }static int HdfDrmPanelSimpleGetModes(struct drm_panel *panel, struct drm_connector *connector) {struct panel_simple *p to_panel_simple(panel);int num 0;HDF_LOGI(HdfDrmPanelSimpleGetModes);if (panel NULL) {HDF_LOGE(panel is NULL);return 0;}if (connector NULL) {HDF_LOGE(connector is NULL);return 0;}// /* probe EDID if a DDC bus is available */// if (p-ddc) {// struct edid *edid drm_get_edid(connector, p-ddc);// drm_connector_update_edid_property(connector, edid);// if (edid) {// num drm_add_edid_modes(connector, edid);// kfree(edid);// }// }/* add hard-coded panel modes */num panel_simple_get_non_edid_modes(p, connector);// /* set up connectors panel orientation property */// drm_connector_set_panel_orientation(connector, p-orientation);return num; }static int HdfDrmPanelSimpleGetTimings(struct drm_panel *panel,unsigned int num_timings,struct display_timing *timings) {struct panel_simple *p to_panel_simple(panel);unsigned int i;if (p-desc-num_timings num_timings)num_timings p-desc-num_timings;if (timings)for (i 0; i num_timings; i)timings[i] p-desc-timings[i];return p-desc-num_timings; }static struct drm_panel_funcs g_hdfDrmPanelFuncs {.disable HdfDrmPanelSimpleDisable,.unprepare HdfDrmPanelSimpleUnprepare,.prepare HdfDrmPanelSimplePrepare,.enable HdfDrmPanelSimpleEnable,.get_modes HdfDrmPanelSimpleGetModes,.get_timings HdfDrmPanelSimpleGetTimings, };static ssize_t SuspendStore(struct device *dev,struct device_attribute *attr, const char *buf, size_t count) {int32_t ret;struct panel_simple *simpePanel dev_get_drvdata(dev);ret HdfDrmPanelSimpleDisable(simpePanel-panel);if (ret ! HDF_SUCCESS) {HDF_LOGE(%s HdfDrmPanelSimpleDisable fail, __func__);return count;}ret HdfDrmPanelSimpleUnprepare(simpePanel-panel);if (ret ! HDF_SUCCESS) {HDF_LOGE(%s HdfDrmPanelSimpleUnprepare fail, __func__);return count;}return count; } static DEVICE_ATTR(suspend, S_IWUSR, NULL, SuspendStore);static ssize_t ResumeStore(struct device *dev,struct device_attribute *attr, const char *buf, size_t count) {int32_t ret;struct panel_simple *simpePanel dev_get_drvdata(dev);ret HdfDrmPanelSimplePrepare(simpePanel-panel);if (ret ! HDF_SUCCESS) {HDF_LOGE(%s HdfDrmPanelSimplePrepare fail, __func__);return count;}ret HdfDrmPanelSimpleEnable(simpePanel-panel);if (ret ! HDF_SUCCESS) {HDF_LOGE(%s HdfDrmPanelSimpleEnable fail, __func__);return count;}return count; } static DEVICE_ATTR(resume, S_IWUSR, NULL, ResumeStore);static ssize_t BacklightStore(struct device *dev,struct device_attribute *attr, const char *buf, size_t count) {int32_t ret;unsigned long level;struct PanelData *panelData NULL;struct panel_simple *simpePanel dev_get_drvdata(dev);struct DispManager *manager GetDispManager();ret kstrtoul(buf, 0, level);if (ret ! 0) {return ret;}HDF_LOGI(%s enter, __func__);OsalMutexLock(manager-dispMutex);panelData manager-panelManager-panel[simpePanel-index];OsalMutexUnlock(manager-dispMutex);ret UpdateBrightness(panelData-blDev, level);if (ret ! HDF_SUCCESS) {HDF_LOGE(%s UpdateBrightness fail, __func__);}return count; } static DEVICE_ATTR(backlight, S_IWUSR, NULL, BacklightStore);#define ATTR_NUM 3 static struct device_attribute *g_panelAttrs[] {dev_attr_suspend,dev_attr_resume,dev_attr_backlight,NULL, };static int32_t HdfDrmPanelSimpleEntryInit(struct HdfDeviceObject *object) {(void)object;uint32_t ret;uint32_t i;uint32_t j;uint32_t panelNum;struct panel_simple *simplePanel NULL;struct DispManager *manager NULL;struct drm_panel *panel NULL;struct device *dev NULL;manager GetDispManager();if (manager NULL) {HDF_LOGE(%s manager is null, __func__);return HDF_FAILURE;}panelNum manager-panelManager-panelNum;for (i 0; i panelNum; i) {simplePanel (struct panel_simple *)manager-panelManager-panel[i]-priv;simplePanel-index i;panel simplePanel-panel;dev panel-dev;drm_panel_init(panel, dev, g_hdfDrmPanelFuncs, simplePanel-desc-connector_type);ret drm_panel_of_backlight(panel);if (ret){HDF_LOGE(%s drm_panel_of_backlight failed %d, __func__, ret);drm_panel_remove(panel);return ret;}drm_panel_add(panel);dev_set_drvdata(dev, simplePanel);for (j 0; j ATTR_NUM; j) {if (device_create_file(dev, g_panelAttrs[j]) ! 0) {HDF_LOGE(%s line %d device_create_file fail, __func__, __LINE__);}}HDF_LOGI(%s panel[%d] registered success, __func__, i);}HDF_LOGI(%s success, __func__);return HDF_SUCCESS; }struct HdfDriverEntry g_hdfDrmPanelSimpleEntry {.moduleVersion 1,.moduleName HDF_DRM_PANEL_SIMPLE,.Init HdfDrmPanelSimpleEntryInit, };HDF_INIT(g_hdfDrmPanelSimpleEntry);2.3.3 修改panel驱动的编译配置文件 前两步添加的文件需要加到编译配置文件里面才可以进行编译如下 Makefile 2.3.4 修改device_info驱动配置文件 device_info驱动配置文件原来加载的是MIPI屏幕驱动这里我们改成加载我们编写的LVDS屏幕驱动如下 device_info.hcs 3. 编译运行 3.1 编译我们修改过的源码 ./build.sh --product-name ok3568 --target-cpu arm643.2 烧录镜像文件并运行查看效果 4. 可能遇到的问题 4.1 pwm背光调节没有反应 原因 RK3568背光功能默认使用原生pwm驱动并且pwm路径已经写死了如下 解决办法 找到设备树里面lvds屏幕所使用的 “pwm-backlight” 节点修改节点名字为backlight如下 或者修改drm_connector.cpp文件中的背光调节功能的文件路径。 5. 参考 标准系统方案之瑞芯微RK3568移植案例
http://www.pierceye.com/news/876344/

相关文章:

  • 做企业网站需要多久论坛网站推广方案
  • 郑州网站优化排名wordpress搭建本地博客
  • 如何获取网站域名证书刚刚北京传来重大消息
  • 找别人做淘客网站他能改pid吗现在中型公司做网站用的是什么框架
  • 泉州晋江网站建设费用海南建设银行官网招聘网站
  • 自己给公司做网站郑州工程建设信息网站
  • 单页网站建站外贸公司网站怎么设计更好
  • 滨州建设工程备案网站网站制作九江
  • 北京网站制作业务如何开展全屋整装定制
  • 网站seo博客刷百度关键词排名
  • 制作企业网站的代码馆陶专业做网站
  • 网站建设简介联系方式PHP 网站开发 重点知识
  • 网页设计网站排行榜浅谈一下网络营销的几个误区
  • 上海网站制作公司报价中国十大咨询公司
  • 软件开发和网站建设哪个好dede网站本地访问速度慢
  • 平安建设网站做写手哪个网站好
  • 服务器硬件影响网站速度网站链接优化
  • 商品网站建设格式最火的做网站源码语言
  • 商城建站系统多少钱商标网官方查询官网
  • 织梦网站怎么做备份昆明航空公司官方网站
  • 大什么的网站建设公司达州网站建设哪家好
  • 漳州网站建设优化房地产网站建设意义
  • 兰州酒店网站建设app推广联盟平台
  • 周边产品设计培训哪家好响应式网站做优化好吗
  • 互联网金融整站seo排名要多少钱
  • 阜宁县城乡建设局新的官方网站重庆智能网站建设哪里有
  • 做ppt常用的网站有哪些建设网络强国要有自己的技术
  • 保险网站有哪些保险网站网页设计与制作课程说明
  • 海外网站seo优化wordpress支持asp.net
  • 什么网站做企业邮箱服务单页网站cms