代码拉取完成,页面将自动刷新
/*
*
* 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.h"
static 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 100
static 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 connector's "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);
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。