mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 06:49:29 -04:00
Merge tag 'drm-misc-next-2025-08-28' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for v6.18: UAPI Changes: atomic: - Reallow no-op async page flips Cross-subsystem Changes: hid: - i2c-hid: Make elan touch controllers power on after panel is enabled video: - Improve pixel-format handling for struct screen_info Core Changes: display: - dp: Fix command length Driver Changes: amdxdna: - Fixes bridge: - Add support for Radxa Ra620 plus DT bindings msm: - Fix VMA allocation panel: - ilitek-ili9881c: Refactor mode setting; Add support for Bestar BSD1218-A101KL68 LCD plus DT bindings - lvds: Add support for Ampire AMP19201200B5TZQW-T03 to DT bindings rockchip: - dsi2: Add support for RK3576 plus DT bindings stm: - Clean up logging vesadrm: - Support 8-bit palette mode Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://lore.kernel.org/r/20250828065714.GA11906@linux.fritz.box
This commit is contained in:
@@ -223,13 +223,13 @@ Userspace components
|
||||
Compiler
|
||||
--------
|
||||
|
||||
Peano is an LLVM based open-source compiler for AMD XDNA Array compute tile
|
||||
available at:
|
||||
Peano is an LLVM based open-source single core compiler for AMD XDNA Array
|
||||
compute tile. Peano is available at:
|
||||
https://github.com/Xilinx/llvm-aie
|
||||
|
||||
The open-source IREE compiler supports graph compilation of ML models for AMD
|
||||
NPU and uses Peano underneath. It is available at:
|
||||
https://github.com/nod-ai/iree-amd-aie
|
||||
IRON is an open-source array compiler for AMD XDNA Array based NPU which uses
|
||||
Peano underneath. IRON is available at:
|
||||
https://github.com/Xilinx/mlir-aie
|
||||
|
||||
Usermode Driver (UMD)
|
||||
---------------------
|
||||
|
||||
@@ -28,6 +28,7 @@ properties:
|
||||
- enum:
|
||||
- adi,adv7123
|
||||
- dumb-vga-dac
|
||||
- radxa,ra620
|
||||
- ti,opa362
|
||||
- ti,ths8134
|
||||
- ti,ths8135
|
||||
|
||||
@@ -18,6 +18,7 @@ properties:
|
||||
- enum:
|
||||
- ampire,am8001280g
|
||||
- bananapi,lhr050h41
|
||||
- bestar,bsd1218-a101kl68
|
||||
- feixin,k101-im2byl02
|
||||
- raspberrypi,dsi-7inch
|
||||
- startek,kd050hdfia020
|
||||
|
||||
@@ -41,6 +41,8 @@ properties:
|
||||
- enum:
|
||||
# Admatec 9904379 10.1" 1024x600 LVDS panel
|
||||
- admatec,9904379
|
||||
# Ampire AMP19201200B5TZQW-T03 10.1" WUXGA (1920x1200) color TFT LCD panel
|
||||
- ampire,amp19201200b5tzqw-t03
|
||||
- auo,b101ew05
|
||||
# AUO G084SN05 V9 8.4" 800x600 LVDS panel
|
||||
- auo,g084sn05
|
||||
|
||||
@@ -12,6 +12,7 @@ maintainers:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- rockchip,rk3576-mipi-dsi2
|
||||
- rockchip,rk3588-mipi-dsi2
|
||||
|
||||
reg:
|
||||
|
||||
@@ -221,6 +221,8 @@ patternProperties:
|
||||
description: BeagleBoard.org Foundation
|
||||
"^belling,.*":
|
||||
description: Shanghai Belling Co., Ltd.
|
||||
"^bestar,.*":
|
||||
description: Shenzhen Bestar Electronic Technology Co., Ltd.
|
||||
"^bhf,.*":
|
||||
description: Beckhoff Automation GmbH & Co. KG
|
||||
"^bigtreetech,.*":
|
||||
|
||||
@@ -785,8 +785,9 @@ static int aie2_get_clock_metadata(struct amdxdna_client *client,
|
||||
|
||||
static int aie2_hwctx_status_cb(struct amdxdna_hwctx *hwctx, void *arg)
|
||||
{
|
||||
struct amdxdna_drm_query_hwctx __user *buf, *tmp __free(kfree) = NULL;
|
||||
struct amdxdna_drm_query_hwctx *tmp __free(kfree) = NULL;
|
||||
struct amdxdna_drm_get_info *get_info_args = arg;
|
||||
struct amdxdna_drm_query_hwctx __user *buf;
|
||||
|
||||
if (get_info_args->buffer_size < sizeof(*tmp))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -261,6 +261,11 @@ static const struct of_device_id simple_bridge_match[] = {
|
||||
.timings = &default_bridge_timings,
|
||||
.connector_type = DRM_MODE_CONNECTOR_VGA,
|
||||
},
|
||||
}, {
|
||||
.compatible = "radxa,ra620",
|
||||
.data = &(const struct simple_bridge_info) {
|
||||
.connector_type = DRM_MODE_CONNECTOR_HDMIA,
|
||||
},
|
||||
}, {
|
||||
.compatible = "ti,opa362",
|
||||
.data = &(const struct simple_bridge_info) {
|
||||
|
||||
@@ -3962,6 +3962,7 @@ int drm_edp_backlight_set_level(struct drm_dp_aux *aux, const struct drm_edp_bac
|
||||
int ret;
|
||||
unsigned int offset = DP_EDP_BACKLIGHT_BRIGHTNESS_MSB;
|
||||
u8 buf[3] = { 0 };
|
||||
size_t len = 2;
|
||||
|
||||
/* The panel uses the PWM for controlling brightness levels */
|
||||
if (!(bl->aux_set || bl->luminance_set))
|
||||
@@ -3974,6 +3975,7 @@ int drm_edp_backlight_set_level(struct drm_dp_aux *aux, const struct drm_edp_bac
|
||||
buf[1] = (level & 0x00ff00) >> 8;
|
||||
buf[2] = (level & 0xff0000) >> 16;
|
||||
offset = DP_EDP_PANEL_TARGET_LUMINANCE_VALUE;
|
||||
len = 3;
|
||||
} else if (bl->lsb_reg_used) {
|
||||
buf[0] = (level & 0xff00) >> 8;
|
||||
buf[1] = (level & 0x00ff);
|
||||
@@ -3981,7 +3983,7 @@ int drm_edp_backlight_set_level(struct drm_dp_aux *aux, const struct drm_edp_bac
|
||||
buf[0] = level;
|
||||
}
|
||||
|
||||
ret = drm_dp_dpcd_write_data(aux, offset, buf, sizeof(buf));
|
||||
ret = drm_dp_dpcd_write_data(aux, offset, buf, len);
|
||||
if (ret < 0) {
|
||||
drm_err(aux->drm_dev,
|
||||
"%s: Failed to write aux backlight level: %d\n",
|
||||
|
||||
@@ -1078,19 +1078,20 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
|
||||
}
|
||||
|
||||
if (async_flip) {
|
||||
/* check if the prop does a nop change */
|
||||
if ((prop != config->prop_fb_id &&
|
||||
prop != config->prop_in_fence_fd &&
|
||||
prop != config->prop_fb_damage_clips)) {
|
||||
ret = drm_atomic_plane_get_property(plane, plane_state,
|
||||
prop, &old_val);
|
||||
ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop);
|
||||
/* no-op changes are always allowed */
|
||||
ret = drm_atomic_plane_get_property(plane, plane_state,
|
||||
prop, &old_val);
|
||||
ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop);
|
||||
|
||||
/* fail everything that isn't no-op or a pure flip */
|
||||
if (ret && prop != config->prop_fb_id &&
|
||||
prop != config->prop_in_fence_fd &&
|
||||
prop != config->prop_fb_damage_clips) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* ask the driver if this non-primary plane is supported */
|
||||
if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
|
||||
ret = -EINVAL;
|
||||
|
||||
if (ret && plane->type != DRM_PLANE_TYPE_PRIMARY) {
|
||||
/* ask the driver if this non-primary plane is supported */
|
||||
if (plane_funcs && plane_funcs->atomic_async_check)
|
||||
ret = plane_funcs->atomic_async_check(plane, state, true);
|
||||
|
||||
|
||||
@@ -817,6 +817,40 @@ void drm_crtc_load_palette_8(struct drm_crtc *crtc, const struct drm_color_lut *
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_load_palette_8);
|
||||
|
||||
static void fill_palette_332(struct drm_crtc *crtc, u16 r, u16 g, u16 b,
|
||||
drm_crtc_set_lut_func set_palette)
|
||||
{
|
||||
unsigned int i = (r << 5) | (g << 2) | b; /* 8-bit palette index */
|
||||
|
||||
/* Expand R (3-bit) G (3-bit) and B (2-bit) values to 16-bit values */
|
||||
r = (r << 13) | (r << 10) | (r << 7) | (r << 4) | (r << 1) | (r >> 2);
|
||||
g = (g << 13) | (g << 10) | (g << 7) | (g << 4) | (g << 1) | (g >> 2);
|
||||
b = (b << 14) | (b << 12) | (b << 10) | (b << 8) | (b << 6) | (b << 4) | (b << 2) | b;
|
||||
|
||||
set_palette(crtc, i, r, g, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_crtc_fill_palette_332 - Programs a default palette for R332-like formats
|
||||
* @crtc: The displaying CRTC
|
||||
* @set_palette: Callback for programming the hardware gamma LUT
|
||||
*
|
||||
* Programs an RGB332 palette to hardware.
|
||||
*/
|
||||
void drm_crtc_fill_palette_332(struct drm_crtc *crtc, drm_crtc_set_lut_func set_palette)
|
||||
{
|
||||
unsigned int r, g, b;
|
||||
|
||||
/* Limits of 8-8-4 are the maximum number of values for each channel. */
|
||||
for (r = 0; r < 8; ++r) {
|
||||
for (g = 0; g < 8; ++g) {
|
||||
for (b = 0; b < 4; ++b)
|
||||
fill_palette_332(crtc, r, g, b, set_palette);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_fill_palette_332);
|
||||
|
||||
static void fill_palette_8(struct drm_crtc *crtc, unsigned int i,
|
||||
drm_crtc_set_lut_func set_palette)
|
||||
{
|
||||
|
||||
@@ -1243,6 +1243,9 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d
|
||||
} else if (dst_format == DRM_FORMAT_BGRX8888) {
|
||||
drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state);
|
||||
return 0;
|
||||
} else if (dst_format == DRM_FORMAT_RGB332) {
|
||||
drm_fb_xrgb8888_to_rgb332(dst, dst_pitch, src, fb, clip, state);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ EXPORT_SYMBOL(drm_of_crtc_port_mask);
|
||||
* and generate the DRM mask of CRTCs which may be attached to this
|
||||
* encoder.
|
||||
*
|
||||
* See Documentation/devicetree/bindings/graph.txt for the bindings.
|
||||
* See https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/graph.yaml
|
||||
* for the bindings.
|
||||
*/
|
||||
uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
|
||||
struct device_node *port)
|
||||
@@ -106,7 +107,9 @@ EXPORT_SYMBOL_GPL(drm_of_component_match_add);
|
||||
* Parse the platform device OF node and bind all the components associated
|
||||
* with the master. Interface ports are added before the encoders in order to
|
||||
* satisfy their .bind requirements
|
||||
* See Documentation/devicetree/bindings/graph.txt for the bindings.
|
||||
*
|
||||
* See https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/graph.yaml
|
||||
* for the bindings.
|
||||
*
|
||||
* Returns zero if successful, or one of the standard error codes if it fails.
|
||||
*/
|
||||
|
||||
@@ -134,6 +134,9 @@ void drm_panel_prepare(struct drm_panel *panel)
|
||||
panel->prepared = true;
|
||||
|
||||
list_for_each_entry(follower, &panel->followers, list) {
|
||||
if (!follower->funcs->panel_prepared)
|
||||
continue;
|
||||
|
||||
ret = follower->funcs->panel_prepared(follower);
|
||||
if (ret < 0)
|
||||
dev_info(panel->dev, "%ps failed: %d\n",
|
||||
@@ -179,6 +182,9 @@ void drm_panel_unprepare(struct drm_panel *panel)
|
||||
mutex_lock(&panel->follower_lock);
|
||||
|
||||
list_for_each_entry(follower, &panel->followers, list) {
|
||||
if (!follower->funcs->panel_unpreparing)
|
||||
continue;
|
||||
|
||||
ret = follower->funcs->panel_unpreparing(follower);
|
||||
if (ret < 0)
|
||||
dev_info(panel->dev, "%ps failed: %d\n",
|
||||
@@ -209,6 +215,7 @@ EXPORT_SYMBOL(drm_panel_unprepare);
|
||||
*/
|
||||
void drm_panel_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct drm_panel_follower *follower;
|
||||
int ret;
|
||||
|
||||
if (!panel)
|
||||
@@ -219,10 +226,12 @@ void drm_panel_enable(struct drm_panel *panel)
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&panel->follower_lock);
|
||||
|
||||
if (panel->funcs && panel->funcs->enable) {
|
||||
ret = panel->funcs->enable(panel);
|
||||
if (ret < 0)
|
||||
return;
|
||||
goto exit;
|
||||
}
|
||||
panel->enabled = true;
|
||||
|
||||
@@ -230,6 +239,19 @@ void drm_panel_enable(struct drm_panel *panel)
|
||||
if (ret < 0)
|
||||
DRM_DEV_INFO(panel->dev, "failed to enable backlight: %d\n",
|
||||
ret);
|
||||
|
||||
list_for_each_entry(follower, &panel->followers, list) {
|
||||
if (!follower->funcs->panel_enabled)
|
||||
continue;
|
||||
|
||||
ret = follower->funcs->panel_enabled(follower);
|
||||
if (ret < 0)
|
||||
dev_info(panel->dev, "%ps failed: %d\n",
|
||||
follower->funcs->panel_enabled, ret);
|
||||
}
|
||||
|
||||
exit:
|
||||
mutex_unlock(&panel->follower_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_panel_enable);
|
||||
|
||||
@@ -243,6 +265,7 @@ EXPORT_SYMBOL(drm_panel_enable);
|
||||
*/
|
||||
void drm_panel_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct drm_panel_follower *follower;
|
||||
int ret;
|
||||
|
||||
if (!panel)
|
||||
@@ -262,6 +285,18 @@ void drm_panel_disable(struct drm_panel *panel)
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&panel->follower_lock);
|
||||
|
||||
list_for_each_entry(follower, &panel->followers, list) {
|
||||
if (!follower->funcs->panel_disabling)
|
||||
continue;
|
||||
|
||||
ret = follower->funcs->panel_disabling(follower);
|
||||
if (ret < 0)
|
||||
dev_info(panel->dev, "%ps failed: %d\n",
|
||||
follower->funcs->panel_disabling, ret);
|
||||
}
|
||||
|
||||
ret = backlight_disable(panel->backlight);
|
||||
if (ret < 0)
|
||||
DRM_DEV_INFO(panel->dev, "failed to disable backlight: %d\n",
|
||||
@@ -270,9 +305,12 @@ void drm_panel_disable(struct drm_panel *panel)
|
||||
if (panel->funcs && panel->funcs->disable) {
|
||||
ret = panel->funcs->disable(panel);
|
||||
if (ret < 0)
|
||||
return;
|
||||
goto exit;
|
||||
}
|
||||
panel->enabled = false;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&panel->follower_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_panel_disable);
|
||||
|
||||
@@ -539,13 +577,13 @@ EXPORT_SYMBOL(drm_is_panel_follower);
|
||||
* @follower_dev: The 'struct device' for the follower.
|
||||
* @follower: The panel follower descriptor for the follower.
|
||||
*
|
||||
* A panel follower is called right after preparing the panel and right before
|
||||
* unpreparing the panel. It's primary intention is to power on an associated
|
||||
* touchscreen, though it could be used for any similar devices. Multiple
|
||||
* devices are allowed the follow the same panel.
|
||||
* A panel follower is called right after preparing/enabling the panel and right
|
||||
* before unpreparing/disabling the panel. It's primary intention is to power on
|
||||
* an associated touchscreen, though it could be used for any similar devices.
|
||||
* Multiple devices are allowed the follow the same panel.
|
||||
*
|
||||
* If a follower is added to a panel that's already been turned on, the
|
||||
* follower's prepare callback is called right away.
|
||||
* If a follower is added to a panel that's already been prepared/enabled, the
|
||||
* follower's prepared/enabled callback is called right away.
|
||||
*
|
||||
* The "panel" property of the follower points to the panel to be followed.
|
||||
*
|
||||
@@ -569,12 +607,18 @@ int drm_panel_add_follower(struct device *follower_dev,
|
||||
mutex_lock(&panel->follower_lock);
|
||||
|
||||
list_add_tail(&follower->list, &panel->followers);
|
||||
if (panel->prepared) {
|
||||
if (panel->prepared && follower->funcs->panel_prepared) {
|
||||
ret = follower->funcs->panel_prepared(follower);
|
||||
if (ret < 0)
|
||||
dev_info(panel->dev, "%ps failed: %d\n",
|
||||
follower->funcs->panel_prepared, ret);
|
||||
}
|
||||
if (panel->enabled && follower->funcs->panel_enabled) {
|
||||
ret = follower->funcs->panel_enabled(follower);
|
||||
if (ret < 0)
|
||||
dev_info(panel->dev, "%ps failed: %d\n",
|
||||
follower->funcs->panel_enabled, ret);
|
||||
}
|
||||
|
||||
mutex_unlock(&panel->follower_lock);
|
||||
|
||||
@@ -587,7 +631,8 @@ EXPORT_SYMBOL(drm_panel_add_follower);
|
||||
* @follower: The panel follower descriptor for the follower.
|
||||
*
|
||||
* Undo drm_panel_add_follower(). This includes calling the follower's
|
||||
* unprepare function if we're removed from a panel that's currently prepared.
|
||||
* unpreparing/disabling function if we're removed from a panel that's currently
|
||||
* prepared/enabled.
|
||||
*
|
||||
* Return: 0 or an error code.
|
||||
*/
|
||||
@@ -598,7 +643,13 @@ void drm_panel_remove_follower(struct drm_panel_follower *follower)
|
||||
|
||||
mutex_lock(&panel->follower_lock);
|
||||
|
||||
if (panel->prepared) {
|
||||
if (panel->enabled && follower->funcs->panel_disabling) {
|
||||
ret = follower->funcs->panel_disabling(follower);
|
||||
if (ret < 0)
|
||||
dev_info(panel->dev, "%ps failed: %d\n",
|
||||
follower->funcs->panel_disabling, ret);
|
||||
}
|
||||
if (panel->prepared && follower->funcs->panel_unpreparing) {
|
||||
ret = follower->funcs->panel_unpreparing(follower);
|
||||
if (ret < 0)
|
||||
dev_info(panel->dev, "%ps failed: %d\n",
|
||||
|
||||
@@ -371,12 +371,6 @@ struct drm_gpuva *
|
||||
msm_gem_vma_new(struct drm_gpuvm *gpuvm, struct drm_gem_object *obj,
|
||||
u64 offset, u64 range_start, u64 range_end)
|
||||
{
|
||||
struct drm_gpuva_op_map op_map = {
|
||||
.va.addr = range_start,
|
||||
.va.range = range_end - range_start,
|
||||
.gem.obj = obj,
|
||||
.gem.offset = offset,
|
||||
};
|
||||
struct msm_gem_vm *vm = to_msm_vm(gpuvm);
|
||||
struct drm_gpuvm_bo *vm_bo;
|
||||
struct msm_gem_vma *vma;
|
||||
@@ -405,6 +399,13 @@ msm_gem_vma_new(struct drm_gpuvm *gpuvm, struct drm_gem_object *obj,
|
||||
if (obj)
|
||||
GEM_WARN_ON((range_end - range_start) > obj->size);
|
||||
|
||||
struct drm_gpuva_op_map op_map = {
|
||||
.va.addr = range_start,
|
||||
.va.range = range_end - range_start,
|
||||
.gem.obj = obj,
|
||||
.gem.offset = offset,
|
||||
};
|
||||
|
||||
drm_gpuva_init_from_op(&vma->base, &op_map);
|
||||
vma->mapped = false;
|
||||
|
||||
|
||||
@@ -1417,6 +1417,200 @@ static const struct ili9881c_instr rpi_7inch_init[] = {
|
||||
ILI9881C_COMMAND_INSTR(0xD3, 0x39),
|
||||
};
|
||||
|
||||
static const struct ili9881c_instr bsd1218_a101kl68_init[] = {
|
||||
ILI9881C_SWITCH_PAGE_INSTR(3),
|
||||
ILI9881C_COMMAND_INSTR(0x01, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x02, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x03, 0x55),
|
||||
ILI9881C_COMMAND_INSTR(0x04, 0x55),
|
||||
ILI9881C_COMMAND_INSTR(0x05, 0x03),
|
||||
ILI9881C_COMMAND_INSTR(0x06, 0x06),
|
||||
ILI9881C_COMMAND_INSTR(0x07, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x08, 0x07),
|
||||
ILI9881C_COMMAND_INSTR(0x09, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x0a, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x0b, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x0c, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x0d, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x0e, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x0f, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x10, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x11, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x12, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x13, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x14, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x15, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x16, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x17, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x18, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x19, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x1a, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x1b, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x1c, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x1d, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x1e, 0xc0),
|
||||
ILI9881C_COMMAND_INSTR(0x1f, 0x80),
|
||||
ILI9881C_COMMAND_INSTR(0x20, 0x04),
|
||||
ILI9881C_COMMAND_INSTR(0x21, 0x03),
|
||||
ILI9881C_COMMAND_INSTR(0x22, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x23, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x24, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x25, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x26, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x27, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x28, 0x33),
|
||||
ILI9881C_COMMAND_INSTR(0x29, 0x33),
|
||||
ILI9881C_COMMAND_INSTR(0x2a, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x2b, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x2c, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x2d, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x2e, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x2f, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x30, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x31, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x32, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x33, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x34, 0x04),
|
||||
ILI9881C_COMMAND_INSTR(0x35, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x36, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x37, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x38, 0x3c),
|
||||
ILI9881C_COMMAND_INSTR(0x39, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x3a, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x3b, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x3c, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x3d, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x3e, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x3f, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x40, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x41, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x42, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x43, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x44, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x50, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x51, 0x11),
|
||||
ILI9881C_COMMAND_INSTR(0x52, 0x44),
|
||||
ILI9881C_COMMAND_INSTR(0x53, 0x55),
|
||||
ILI9881C_COMMAND_INSTR(0x54, 0x88),
|
||||
ILI9881C_COMMAND_INSTR(0x55, 0xab),
|
||||
ILI9881C_COMMAND_INSTR(0x56, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x57, 0x11),
|
||||
ILI9881C_COMMAND_INSTR(0x58, 0x22),
|
||||
ILI9881C_COMMAND_INSTR(0x59, 0x33),
|
||||
ILI9881C_COMMAND_INSTR(0x5a, 0x44),
|
||||
ILI9881C_COMMAND_INSTR(0x5b, 0x55),
|
||||
ILI9881C_COMMAND_INSTR(0x5c, 0x66),
|
||||
ILI9881C_COMMAND_INSTR(0x5d, 0x77),
|
||||
ILI9881C_COMMAND_INSTR(0x5e, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0x5f, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x60, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x61, 0x0a),
|
||||
ILI9881C_COMMAND_INSTR(0x62, 0x09),
|
||||
ILI9881C_COMMAND_INSTR(0x63, 0x08),
|
||||
ILI9881C_COMMAND_INSTR(0x64, 0x13),
|
||||
ILI9881C_COMMAND_INSTR(0x65, 0x12),
|
||||
ILI9881C_COMMAND_INSTR(0x66, 0x11),
|
||||
ILI9881C_COMMAND_INSTR(0x67, 0x10),
|
||||
ILI9881C_COMMAND_INSTR(0x68, 0x0f),
|
||||
ILI9881C_COMMAND_INSTR(0x69, 0x0e),
|
||||
ILI9881C_COMMAND_INSTR(0x6a, 0x0d),
|
||||
ILI9881C_COMMAND_INSTR(0x6b, 0x0c),
|
||||
ILI9881C_COMMAND_INSTR(0x6c, 0x06),
|
||||
ILI9881C_COMMAND_INSTR(0x6d, 0x07),
|
||||
ILI9881C_COMMAND_INSTR(0x6e, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x6f, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x70, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x71, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x72, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x73, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x74, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x75, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x76, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x77, 0x0a),
|
||||
ILI9881C_COMMAND_INSTR(0x78, 0x06),
|
||||
ILI9881C_COMMAND_INSTR(0x79, 0x07),
|
||||
ILI9881C_COMMAND_INSTR(0x7a, 0x10),
|
||||
ILI9881C_COMMAND_INSTR(0x7b, 0x11),
|
||||
ILI9881C_COMMAND_INSTR(0x7c, 0x12),
|
||||
ILI9881C_COMMAND_INSTR(0x7d, 0x13),
|
||||
ILI9881C_COMMAND_INSTR(0x7e, 0x0c),
|
||||
ILI9881C_COMMAND_INSTR(0x7f, 0x0d),
|
||||
ILI9881C_COMMAND_INSTR(0x80, 0x0e),
|
||||
ILI9881C_COMMAND_INSTR(0x81, 0x0f),
|
||||
ILI9881C_COMMAND_INSTR(0x82, 0x09),
|
||||
ILI9881C_COMMAND_INSTR(0x83, 0x08),
|
||||
ILI9881C_COMMAND_INSTR(0x84, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x85, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x86, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x87, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x88, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x89, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x8a, 0x02),
|
||||
|
||||
ILI9881C_SWITCH_PAGE_INSTR(4),
|
||||
ILI9881C_COMMAND_INSTR(0x6e, 0x2a),
|
||||
ILI9881C_COMMAND_INSTR(0x6f, 0x37),
|
||||
ILI9881C_COMMAND_INSTR(0x3a, 0x24),
|
||||
ILI9881C_COMMAND_INSTR(0x8d, 0x19),
|
||||
ILI9881C_COMMAND_INSTR(0x87, 0xba),
|
||||
ILI9881C_COMMAND_INSTR(0xb2, 0xd1),
|
||||
ILI9881C_COMMAND_INSTR(0x88, 0x0b),
|
||||
ILI9881C_COMMAND_INSTR(0x38, 0x01),
|
||||
ILI9881C_COMMAND_INSTR(0x39, 0x00),
|
||||
ILI9881C_COMMAND_INSTR(0xb5, 0x02),
|
||||
ILI9881C_COMMAND_INSTR(0x31, 0x25),
|
||||
ILI9881C_COMMAND_INSTR(0x3b, 0x98),
|
||||
|
||||
ILI9881C_SWITCH_PAGE_INSTR(1),
|
||||
ILI9881C_COMMAND_INSTR(0x22, 0x0a),
|
||||
ILI9881C_COMMAND_INSTR(0x31, 0x0c),
|
||||
ILI9881C_COMMAND_INSTR(0x53, 0x40),
|
||||
ILI9881C_COMMAND_INSTR(0x55, 0x45),
|
||||
ILI9881C_COMMAND_INSTR(0x50, 0xb7),
|
||||
ILI9881C_COMMAND_INSTR(0x51, 0xb2),
|
||||
ILI9881C_COMMAND_INSTR(0x60, 0x07),
|
||||
ILI9881C_COMMAND_INSTR(0xa0, 0x22),
|
||||
ILI9881C_COMMAND_INSTR(0xa1, 0x3f),
|
||||
ILI9881C_COMMAND_INSTR(0xa2, 0x4e),
|
||||
ILI9881C_COMMAND_INSTR(0xa3, 0x17),
|
||||
ILI9881C_COMMAND_INSTR(0xa4, 0x1a),
|
||||
ILI9881C_COMMAND_INSTR(0xa5, 0x2d),
|
||||
ILI9881C_COMMAND_INSTR(0xa6, 0x21),
|
||||
ILI9881C_COMMAND_INSTR(0xa7, 0x22),
|
||||
ILI9881C_COMMAND_INSTR(0xa8, 0xc4),
|
||||
ILI9881C_COMMAND_INSTR(0xa9, 0x1b),
|
||||
ILI9881C_COMMAND_INSTR(0xaa, 0x25),
|
||||
ILI9881C_COMMAND_INSTR(0xab, 0xa7),
|
||||
ILI9881C_COMMAND_INSTR(0xac, 0x1a),
|
||||
ILI9881C_COMMAND_INSTR(0xad, 0x19),
|
||||
ILI9881C_COMMAND_INSTR(0xae, 0x4b),
|
||||
ILI9881C_COMMAND_INSTR(0xaf, 0x1f),
|
||||
ILI9881C_COMMAND_INSTR(0xb0, 0x2a),
|
||||
ILI9881C_COMMAND_INSTR(0xb1, 0x59),
|
||||
ILI9881C_COMMAND_INSTR(0xb2, 0x64),
|
||||
ILI9881C_COMMAND_INSTR(0xb3, 0x3f),
|
||||
ILI9881C_COMMAND_INSTR(0xc0, 0x22),
|
||||
ILI9881C_COMMAND_INSTR(0xc1, 0x48),
|
||||
ILI9881C_COMMAND_INSTR(0xc2, 0x59),
|
||||
ILI9881C_COMMAND_INSTR(0xc3, 0x15),
|
||||
ILI9881C_COMMAND_INSTR(0xc4, 0x15),
|
||||
ILI9881C_COMMAND_INSTR(0xc5, 0x28),
|
||||
ILI9881C_COMMAND_INSTR(0xc6, 0x1c),
|
||||
ILI9881C_COMMAND_INSTR(0xc7, 0x1e),
|
||||
ILI9881C_COMMAND_INSTR(0xc8, 0xc4),
|
||||
ILI9881C_COMMAND_INSTR(0xc9, 0x1c),
|
||||
ILI9881C_COMMAND_INSTR(0xca, 0x2b),
|
||||
ILI9881C_COMMAND_INSTR(0xcb, 0xa3),
|
||||
ILI9881C_COMMAND_INSTR(0xcc, 0x1f),
|
||||
ILI9881C_COMMAND_INSTR(0xcd, 0x1e),
|
||||
ILI9881C_COMMAND_INSTR(0xce, 0x52),
|
||||
ILI9881C_COMMAND_INSTR(0xcf, 0x24),
|
||||
ILI9881C_COMMAND_INSTR(0xd0, 0x2a),
|
||||
ILI9881C_COMMAND_INSTR(0xd1, 0x58),
|
||||
ILI9881C_COMMAND_INSTR(0xd2, 0x68),
|
||||
ILI9881C_COMMAND_INSTR(0xd3, 0x3f),
|
||||
};
|
||||
|
||||
static inline struct ili9881c *panel_to_ili9881c(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct ili9881c, panel);
|
||||
@@ -1433,33 +1627,24 @@ static inline struct ili9881c *panel_to_ili9881c(struct drm_panel *panel)
|
||||
* So before any attempt at sending a command or data, we have to be
|
||||
* sure if we're in the right page or not.
|
||||
*/
|
||||
static int ili9881c_switch_page(struct ili9881c *ctx, u8 page)
|
||||
static void ili9881c_switch_page(struct mipi_dsi_multi_context *mctx, u8 page)
|
||||
{
|
||||
u8 buf[4] = { 0xff, 0x98, 0x81, page };
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(ctx->dsi, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
mipi_dsi_dcs_write_buffer_multi(mctx, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static int ili9881c_send_cmd_data(struct ili9881c *ctx, u8 cmd, u8 data)
|
||||
static void ili9881c_send_cmd_data(struct mipi_dsi_multi_context *mctx, u8 cmd, u8 data)
|
||||
{
|
||||
u8 buf[2] = { cmd, data };
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(ctx->dsi, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
mipi_dsi_dcs_write_buffer_multi(mctx, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static int ili9881c_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct ili9881c *ctx = panel_to_ili9881c(panel);
|
||||
struct mipi_dsi_multi_context mctx = { .dsi = ctx->dsi };
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
@@ -1480,61 +1665,39 @@ static int ili9881c_prepare(struct drm_panel *panel)
|
||||
const struct ili9881c_instr *instr = &ctx->desc->init[i];
|
||||
|
||||
if (instr->op == ILI9881C_SWITCH_PAGE)
|
||||
ret = ili9881c_switch_page(ctx, instr->arg.page);
|
||||
ili9881c_switch_page(&mctx, instr->arg.page);
|
||||
else if (instr->op == ILI9881C_COMMAND)
|
||||
ret = ili9881c_send_cmd_data(ctx, instr->arg.cmd.cmd,
|
||||
instr->arg.cmd.data);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
ili9881c_send_cmd_data(&mctx, instr->arg.cmd.cmd,
|
||||
instr->arg.cmd.data);
|
||||
}
|
||||
|
||||
ret = ili9881c_switch_page(ctx, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
ili9881c_switch_page(&mctx, 0);
|
||||
|
||||
if (ctx->address_mode) {
|
||||
ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_SET_ADDRESS_MODE,
|
||||
&ctx->address_mode,
|
||||
sizeof(ctx->address_mode));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
if (ctx->address_mode)
|
||||
ili9881c_send_cmd_data(&mctx, MIPI_DCS_SET_ADDRESS_MODE,
|
||||
ctx->address_mode);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(ctx->dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(ctx->dsi);
|
||||
if (ret)
|
||||
return ret;
|
||||
mipi_dsi_dcs_set_tear_on_multi(&mctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&mctx);
|
||||
mipi_dsi_msleep(&mctx, 120);
|
||||
mipi_dsi_dcs_set_display_on_multi(&mctx);
|
||||
if (mctx.accum_err)
|
||||
goto disable_power;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ili9881c_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct ili9881c *ctx = panel_to_ili9881c(panel);
|
||||
|
||||
msleep(120);
|
||||
|
||||
mipi_dsi_dcs_set_display_on(ctx->dsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ili9881c_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct ili9881c *ctx = panel_to_ili9881c(panel);
|
||||
|
||||
return mipi_dsi_dcs_set_display_off(ctx->dsi);
|
||||
disable_power:
|
||||
regulator_disable(ctx->power);
|
||||
return mctx.accum_err;
|
||||
}
|
||||
|
||||
static int ili9881c_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct ili9881c *ctx = panel_to_ili9881c(panel);
|
||||
struct mipi_dsi_multi_context mctx = { .dsi = ctx->dsi };
|
||||
|
||||
mipi_dsi_dcs_enter_sleep_mode(ctx->dsi);
|
||||
mipi_dsi_dcs_set_display_off_multi(&mctx);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&mctx);
|
||||
regulator_disable(ctx->power);
|
||||
gpiod_set_value_cansleep(ctx->reset, 1);
|
||||
|
||||
@@ -1660,6 +1823,23 @@ static const struct drm_display_mode rpi_7inch_default_mode = {
|
||||
.height_mm = 151,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode bsd1218_a101kl68_default_mode = {
|
||||
.clock = 70000,
|
||||
|
||||
.hdisplay = 800,
|
||||
.hsync_start = 800 + 40,
|
||||
.hsync_end = 800 + 40 + 20,
|
||||
.htotal = 800 + 40 + 20 + 20,
|
||||
|
||||
.vdisplay = 1280,
|
||||
.vsync_start = 1280 + 20,
|
||||
.vsync_end = 1280 + 20 + 4,
|
||||
.vtotal = 1280 + 20 + 4 + 20,
|
||||
|
||||
.width_mm = 120,
|
||||
.height_mm = 170,
|
||||
};
|
||||
|
||||
static int ili9881c_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
@@ -1706,8 +1886,6 @@ static enum drm_panel_orientation ili9881c_get_orientation(struct drm_panel *pan
|
||||
static const struct drm_panel_funcs ili9881c_funcs = {
|
||||
.prepare = ili9881c_prepare,
|
||||
.unprepare = ili9881c_unprepare,
|
||||
.enable = ili9881c_enable,
|
||||
.disable = ili9881c_disable,
|
||||
.get_modes = ili9881c_get_modes,
|
||||
.get_orientation = ili9881c_get_orientation,
|
||||
};
|
||||
@@ -1830,8 +2008,18 @@ static const struct ili9881c_desc rpi_7inch_desc = {
|
||||
.lanes = 2,
|
||||
};
|
||||
|
||||
static const struct ili9881c_desc bsd1218_a101kl68_desc = {
|
||||
.init = bsd1218_a101kl68_init,
|
||||
.init_length = ARRAY_SIZE(bsd1218_a101kl68_init),
|
||||
.mode = &bsd1218_a101kl68_default_mode,
|
||||
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET,
|
||||
.lanes = 4,
|
||||
};
|
||||
|
||||
static const struct of_device_id ili9881c_of_match[] = {
|
||||
{ .compatible = "bananapi,lhr050h41", .data = &lhr050h41_desc },
|
||||
{ .compatible = "bestar,bsd1218-a101kl68", .data = &bsd1218_a101kl68_desc },
|
||||
{ .compatible = "feixin,k101-im2byl02", .data = &k101_im2byl02_desc },
|
||||
{ .compatible = "startek,kd050hdfia020", .data = &kd050hdfia020_desc },
|
||||
{ .compatible = "tdo,tl050hdv35", .data = &tl050hdv35_desc },
|
||||
|
||||
@@ -233,8 +233,10 @@ static int jdi_panel_prepare(struct drm_panel *panel)
|
||||
mipi_dsi_dual(mipi_dsi_dcs_set_display_on_multi,
|
||||
&dsi_ctx, jdi->link1, jdi->link2);
|
||||
|
||||
if (dsi_ctx.accum_err < 0)
|
||||
if (dsi_ctx.accum_err < 0) {
|
||||
err = dsi_ctx.accum_err;
|
||||
goto poweroff;
|
||||
}
|
||||
|
||||
jdi->link1->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
jdi->link2->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
@@ -437,6 +437,15 @@ static void dw_mipi_dsi2_rockchip_remove(struct platform_device *pdev)
|
||||
dw_mipi_dsi2_remove(dsi2->dmd);
|
||||
}
|
||||
|
||||
static const struct dsigrf_reg rk3576_dsi_grf_reg_fields[MAX_FIELDS] = {
|
||||
[TXREQCLKHS_EN] = { 0x0028, 1, 1 },
|
||||
[GATING_EN] = { 0x0028, 0, 0 },
|
||||
[IPI_SHUTDN] = { 0x0028, 3, 3 },
|
||||
[IPI_COLORM] = { 0x0028, 2, 2 },
|
||||
[IPI_COLOR_DEPTH] = { 0x0028, 8, 11 },
|
||||
[IPI_FORMAT] = { 0x0028, 4, 7 },
|
||||
};
|
||||
|
||||
static const struct dsigrf_reg rk3588_dsi0_grf_reg_fields[MAX_FIELDS] = {
|
||||
[TXREQCLKHS_EN] = { 0x0000, 11, 11 },
|
||||
[GATING_EN] = { 0x0000, 10, 10 },
|
||||
@@ -455,6 +464,15 @@ static const struct dsigrf_reg rk3588_dsi1_grf_reg_fields[MAX_FIELDS] = {
|
||||
[IPI_FORMAT] = { 0x0004, 0, 3 },
|
||||
};
|
||||
|
||||
static const struct rockchip_dw_dsi2_chip_data rk3576_chip_data[] = {
|
||||
{
|
||||
.reg = 0x27d80000,
|
||||
.grf_regs = rk3576_dsi_grf_reg_fields,
|
||||
.max_bit_rate_per_lane = 2500000ULL,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static const struct rockchip_dw_dsi2_chip_data rk3588_chip_data[] = {
|
||||
{
|
||||
.reg = 0xfde20000,
|
||||
@@ -470,6 +488,9 @@ static const struct rockchip_dw_dsi2_chip_data rk3588_chip_data[] = {
|
||||
|
||||
static const struct of_device_id dw_mipi_dsi2_rockchip_dt_ids[] = {
|
||||
{
|
||||
.compatible = "rockchip,rk3576-mipi-dsi2",
|
||||
.data = &rk3576_chip_data,
|
||||
}, {
|
||||
.compatible = "rockchip,rk3588-mipi-dsi2",
|
||||
.data = &rk3588_chip_data,
|
||||
},
|
||||
|
||||
@@ -641,7 +641,7 @@ static inline void ltdc_set_ycbcr_config(struct drm_plane *plane, u32 drm_pix_fm
|
||||
break;
|
||||
default:
|
||||
/* RGB or not a YCbCr supported format */
|
||||
DRM_ERROR("Unsupported pixel format: %u\n", drm_pix_fmt);
|
||||
drm_err(plane->dev, "Unsupported pixel format: %u\n", drm_pix_fmt);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -664,18 +664,19 @@ static inline void ltdc_set_ycbcr_coeffs(struct drm_plane *plane)
|
||||
u32 lofs = plane->index * LAY_OFS;
|
||||
|
||||
if (enc != DRM_COLOR_YCBCR_BT601 && enc != DRM_COLOR_YCBCR_BT709) {
|
||||
DRM_ERROR("color encoding %d not supported, use bt601 by default\n", enc);
|
||||
drm_err(plane->dev, "color encoding %d not supported, use bt601 by default\n", enc);
|
||||
/* set by default color encoding to DRM_COLOR_YCBCR_BT601 */
|
||||
enc = DRM_COLOR_YCBCR_BT601;
|
||||
}
|
||||
|
||||
if (ran != DRM_COLOR_YCBCR_LIMITED_RANGE && ran != DRM_COLOR_YCBCR_FULL_RANGE) {
|
||||
DRM_ERROR("color range %d not supported, use limited range by default\n", ran);
|
||||
drm_err(plane->dev,
|
||||
"color range %d not supported, use limited range by default\n", ran);
|
||||
/* set by default color range to DRM_COLOR_YCBCR_LIMITED_RANGE */
|
||||
ran = DRM_COLOR_YCBCR_LIMITED_RANGE;
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("Color encoding=%d, range=%d\n", enc, ran);
|
||||
drm_err(plane->dev, "Color encoding=%d, range=%d\n", enc, ran);
|
||||
regmap_write(ldev->regmap, LTDC_L1CYR0R + lofs,
|
||||
ltdc_ycbcr2rgb_coeffs[enc][ran][0]);
|
||||
regmap_write(ldev->regmap, LTDC_L1CYR1R + lofs,
|
||||
@@ -774,7 +775,7 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
struct ltdc_device *ldev = crtc_to_ltdc(crtc);
|
||||
struct drm_device *ddev = crtc->dev;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(crtc->dev, "\n");
|
||||
|
||||
pm_runtime_get_sync(ddev->dev);
|
||||
|
||||
@@ -798,7 +799,7 @@ static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
struct drm_device *ddev = crtc->dev;
|
||||
int layer_index = 0;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(crtc->dev, "\n");
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
|
||||
@@ -837,7 +838,7 @@ ltdc_crtc_mode_valid(struct drm_crtc *crtc,
|
||||
|
||||
result = clk_round_rate(ldev->pixel_clk, target);
|
||||
|
||||
DRM_DEBUG_DRIVER("clk rate target %d, available %d\n", target, result);
|
||||
drm_dbg_driver(crtc->dev, "clk rate target %d, available %d\n", target, result);
|
||||
|
||||
/* Filter modes according to the max frequency supported by the pads */
|
||||
if (result > ldev->caps.pad_max_freq_hz)
|
||||
@@ -872,14 +873,14 @@ static bool ltdc_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
int rate = mode->clock * 1000;
|
||||
|
||||
if (clk_set_rate(ldev->pixel_clk, rate) < 0) {
|
||||
DRM_ERROR("Cannot set rate (%dHz) for pixel clk\n", rate);
|
||||
drm_err(crtc->dev, "Cannot set rate (%dHz) for pixel clk\n", rate);
|
||||
return false;
|
||||
}
|
||||
|
||||
adjusted_mode->clock = clk_get_rate(ldev->pixel_clk) / 1000;
|
||||
|
||||
DRM_DEBUG_DRIVER("requested clock %dkHz, adjusted clock %dkHz\n",
|
||||
mode->clock, adjusted_mode->clock);
|
||||
drm_dbg_driver(crtc->dev, "requested clock %dkHz, adjusted clock %dkHz\n",
|
||||
mode->clock, adjusted_mode->clock);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -934,20 +935,20 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
if (!pm_runtime_active(ddev->dev)) {
|
||||
ret = pm_runtime_get_sync(ddev->dev);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to set mode, cannot get sync\n");
|
||||
drm_err(crtc->dev, "Failed to set mode, cannot get sync\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("CRTC:%d mode:%s\n", crtc->base.id, mode->name);
|
||||
DRM_DEBUG_DRIVER("Video mode: %dx%d", mode->hdisplay, mode->vdisplay);
|
||||
DRM_DEBUG_DRIVER(" hfp %d hbp %d hsl %d vfp %d vbp %d vsl %d\n",
|
||||
mode->hsync_start - mode->hdisplay,
|
||||
mode->htotal - mode->hsync_end,
|
||||
mode->hsync_end - mode->hsync_start,
|
||||
mode->vsync_start - mode->vdisplay,
|
||||
mode->vtotal - mode->vsync_end,
|
||||
mode->vsync_end - mode->vsync_start);
|
||||
drm_dbg_driver(crtc->dev, "CRTC:%d mode:%s\n", crtc->base.id, mode->name);
|
||||
drm_dbg_driver(crtc->dev, "Video mode: %dx%d", mode->hdisplay, mode->vdisplay);
|
||||
drm_dbg_driver(crtc->dev, " hfp %d hbp %d hsl %d vfp %d vbp %d vsl %d\n",
|
||||
mode->hsync_start - mode->hdisplay,
|
||||
mode->htotal - mode->hsync_end,
|
||||
mode->hsync_end - mode->hsync_start,
|
||||
mode->vsync_start - mode->vdisplay,
|
||||
mode->vtotal - mode->vsync_end,
|
||||
mode->vsync_end - mode->vsync_start);
|
||||
|
||||
/* Convert video timings to ltdc timings */
|
||||
hsync = mode->hsync_end - mode->hsync_start - 1;
|
||||
@@ -1033,7 +1034,7 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
struct drm_device *ddev = crtc->dev;
|
||||
struct drm_pending_vblank_event *event = crtc->state->event;
|
||||
|
||||
DRM_DEBUG_ATOMIC("\n");
|
||||
drm_dbg_atomic(crtc->dev, "\n");
|
||||
|
||||
ltdc_crtc_update_clut(crtc);
|
||||
|
||||
@@ -1121,7 +1122,7 @@ static int ltdc_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
struct ltdc_device *ldev = crtc_to_ltdc(crtc);
|
||||
struct drm_crtc_state *state = crtc->state;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(crtc->dev, "\n");
|
||||
|
||||
if (state->enable)
|
||||
regmap_set_bits(ldev->regmap, LTDC_IER, IER_LIE);
|
||||
@@ -1135,7 +1136,7 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct ltdc_device *ldev = crtc_to_ltdc(crtc);
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(crtc->dev, "\n");
|
||||
regmap_clear_bits(ldev->regmap, LTDC_IER, IER_LIE);
|
||||
}
|
||||
|
||||
@@ -1144,11 +1145,11 @@ static int ltdc_crtc_set_crc_source(struct drm_crtc *crtc, const char *source)
|
||||
struct ltdc_device *ldev;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
if (!crtc)
|
||||
return -ENODEV;
|
||||
|
||||
drm_dbg_driver(crtc->dev, "\n");
|
||||
|
||||
ldev = crtc_to_ltdc(crtc);
|
||||
|
||||
if (source && strcmp(source, "auto") == 0) {
|
||||
@@ -1168,14 +1169,14 @@ static int ltdc_crtc_set_crc_source(struct drm_crtc *crtc, const char *source)
|
||||
static int ltdc_crtc_verify_crc_source(struct drm_crtc *crtc,
|
||||
const char *source, size_t *values_cnt)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
if (!crtc)
|
||||
return -ENODEV;
|
||||
|
||||
drm_dbg_driver(crtc->dev, "\n");
|
||||
|
||||
if (source && strcmp(source, "auto") != 0) {
|
||||
DRM_DEBUG_DRIVER("Unknown CRC source %s for %s\n",
|
||||
source, crtc->name);
|
||||
drm_dbg_driver(crtc->dev, "Unknown CRC source %s for %s\n",
|
||||
source, crtc->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1233,7 +1234,7 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_framebuffer *fb = new_plane_state->fb;
|
||||
u32 src_w, src_h;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(plane->dev, "\n");
|
||||
|
||||
if (!fb)
|
||||
return 0;
|
||||
@@ -1244,7 +1245,7 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane,
|
||||
|
||||
/* Reject scaling */
|
||||
if (src_w != new_plane_state->crtc_w || src_h != new_plane_state->crtc_h) {
|
||||
DRM_DEBUG_DRIVER("Scaling is not supported");
|
||||
drm_dbg_driver(plane->dev, "Scaling is not supported");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1270,7 +1271,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
enum ltdc_pix_fmt pf;
|
||||
|
||||
if (!newstate->crtc || !fb) {
|
||||
DRM_DEBUG_DRIVER("fb or crtc NULL");
|
||||
drm_dbg_driver(plane->dev, "fb or crtc NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1280,11 +1281,11 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
src_w = newstate->src_w >> 16;
|
||||
src_h = newstate->src_h >> 16;
|
||||
|
||||
DRM_DEBUG_DRIVER("plane:%d fb:%d (%dx%d)@(%d,%d) -> (%dx%d)@(%d,%d)\n",
|
||||
plane->base.id, fb->base.id,
|
||||
src_w, src_h, src_x, src_y,
|
||||
newstate->crtc_w, newstate->crtc_h,
|
||||
newstate->crtc_x, newstate->crtc_y);
|
||||
drm_dbg_driver(plane->dev, "plane:%d fb:%d (%dx%d)@(%d,%d) -> (%dx%d)@(%d,%d)\n",
|
||||
plane->base.id, fb->base.id,
|
||||
src_w, src_h, src_x, src_y,
|
||||
newstate->crtc_w, newstate->crtc_h,
|
||||
newstate->crtc_x, newstate->crtc_y);
|
||||
|
||||
regmap_read(ldev->regmap, LTDC_BPCR, &bpcr);
|
||||
|
||||
@@ -1312,8 +1313,8 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
val = ltdc_set_flexible_pixel_format(plane, pf);
|
||||
|
||||
if (val == NB_PF) {
|
||||
DRM_ERROR("Pixel format %.4s not supported\n",
|
||||
(char *)&fb->format->format);
|
||||
drm_err(fb->dev, "Pixel format %.4s not supported\n",
|
||||
(char *)&fb->format->format);
|
||||
val = 0; /* set by default ARGB 32 bits */
|
||||
}
|
||||
regmap_write_bits(ldev->regmap, LTDC_L1PFCR + lofs, LXPFCR_PF, val);
|
||||
@@ -1350,7 +1351,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
|
||||
if (newstate->rotation & DRM_MODE_REFLECT_Y)
|
||||
paddr += (fb->pitches[0] * (y1 - y0));
|
||||
|
||||
DRM_DEBUG_DRIVER("fb: phys 0x%08x", paddr);
|
||||
drm_dbg_driver(fb->dev, "fb: phys 0x%08x", paddr);
|
||||
regmap_write(ldev->regmap, LTDC_L1CFBAR + lofs, paddr);
|
||||
|
||||
/* Configures the color frame buffer pitch in bytes & line length */
|
||||
@@ -1517,8 +1518,8 @@ static void ltdc_plane_atomic_disable(struct drm_plane *plane,
|
||||
regmap_write_bits(ldev->regmap, LTDC_L1RCR + lofs,
|
||||
LXRCR_IMR | LXRCR_VBR | LXRCR_GRMSK, LXRCR_VBR);
|
||||
|
||||
DRM_DEBUG_DRIVER("CRTC:%d plane:%d\n",
|
||||
oldstate->crtc->base.id, plane->base.id);
|
||||
drm_dbg_driver(plane->dev, "CRTC:%d plane:%d\n",
|
||||
oldstate->crtc->base.id, plane->base.id);
|
||||
}
|
||||
|
||||
static void ltdc_plane_atomic_print_state(struct drm_printer *p,
|
||||
@@ -1632,7 +1633,7 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
|
||||
|
||||
drm_plane_create_alpha_property(plane);
|
||||
|
||||
DRM_DEBUG_DRIVER("plane:%d created\n", plane->base.id);
|
||||
drm_dbg_driver(plane->dev, "plane:%d created\n", plane->base.id);
|
||||
|
||||
return plane;
|
||||
}
|
||||
@@ -1647,7 +1648,7 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
|
||||
|
||||
primary = ltdc_plane_create(ddev, DRM_PLANE_TYPE_PRIMARY, 0);
|
||||
if (!primary) {
|
||||
DRM_ERROR("Can not create primary plane\n");
|
||||
drm_err(ddev, "Can not create primary plane\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1668,7 +1669,7 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
|
||||
ret = drmm_crtc_init_with_planes(ddev, crtc, primary, NULL,
|
||||
<dc_crtc_funcs, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("Can not initialize CRTC\n");
|
||||
drm_err(ddev, "Can not initialize CRTC\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1677,13 +1678,13 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
|
||||
drm_mode_crtc_set_gamma_size(crtc, CLUT_SIZE);
|
||||
drm_crtc_enable_color_mgmt(crtc, 0, false, CLUT_SIZE);
|
||||
|
||||
DRM_DEBUG_DRIVER("CRTC:%d created\n", crtc->base.id);
|
||||
drm_dbg_driver(ddev, "CRTC:%d created\n", crtc->base.id);
|
||||
|
||||
/* Add planes. Note : the first layer is used by primary plane */
|
||||
for (i = 1; i < ldev->caps.nb_layers; i++) {
|
||||
overlay = ltdc_plane_create(ddev, DRM_PLANE_TYPE_OVERLAY, i);
|
||||
if (!overlay) {
|
||||
DRM_ERROR("Can not create overlay plane %d\n", i);
|
||||
drm_err(ddev, "Can not create overlay plane %d\n", i);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (ldev->caps.dynamic_zorder)
|
||||
@@ -1704,7 +1705,7 @@ static void ltdc_encoder_disable(struct drm_encoder *encoder)
|
||||
struct drm_device *ddev = encoder->dev;
|
||||
struct ltdc_device *ldev = ddev->dev_private;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(encoder->dev, "\n");
|
||||
|
||||
/* Disable LTDC */
|
||||
regmap_clear_bits(ldev->regmap, LTDC_GCR, GCR_LTDCEN);
|
||||
@@ -1718,7 +1719,7 @@ static void ltdc_encoder_enable(struct drm_encoder *encoder)
|
||||
struct drm_device *ddev = encoder->dev;
|
||||
struct ltdc_device *ldev = ddev->dev_private;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(encoder->dev, "\n");
|
||||
|
||||
/* set fifo underrun threshold register */
|
||||
if (ldev->caps.fifo_threshold)
|
||||
@@ -1734,7 +1735,7 @@ static void ltdc_encoder_mode_set(struct drm_encoder *encoder,
|
||||
{
|
||||
struct drm_device *ddev = encoder->dev;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(encoder->dev, "\n");
|
||||
|
||||
/*
|
||||
* Set to default state the pinctrl only with DPI type.
|
||||
@@ -1770,7 +1771,7 @@ static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_DEBUG_DRIVER("Bridge encoder:%d created\n", encoder->base.id);
|
||||
drm_dbg_driver(encoder->dev, "Bridge encoder:%d created\n", encoder->base.id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1870,7 +1871,7 @@ void ltdc_suspend(struct drm_device *ddev)
|
||||
{
|
||||
struct ltdc_device *ldev = ddev->dev_private;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(ddev, "\n");
|
||||
clk_disable_unprepare(ldev->pixel_clk);
|
||||
}
|
||||
|
||||
@@ -1879,11 +1880,11 @@ int ltdc_resume(struct drm_device *ddev)
|
||||
struct ltdc_device *ldev = ddev->dev_private;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(ddev, "\n");
|
||||
|
||||
ret = clk_prepare_enable(ldev->pixel_clk);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to enable pixel clock (%d)\n", ret);
|
||||
drm_err(ddev, "failed to enable pixel clock (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1903,7 +1904,7 @@ int ltdc_load(struct drm_device *ddev)
|
||||
int irq, i, nb_endpoints;
|
||||
int ret = -ENODEV;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(ddev, "\n");
|
||||
|
||||
/* Get number of endpoints */
|
||||
nb_endpoints = of_graph_get_endpoint_count(np);
|
||||
@@ -1913,12 +1914,12 @@ int ltdc_load(struct drm_device *ddev)
|
||||
ldev->pixel_clk = devm_clk_get(dev, "lcd");
|
||||
if (IS_ERR(ldev->pixel_clk)) {
|
||||
if (PTR_ERR(ldev->pixel_clk) != -EPROBE_DEFER)
|
||||
DRM_ERROR("Unable to get lcd clock\n");
|
||||
drm_err(ddev, "Unable to get lcd clock\n");
|
||||
return PTR_ERR(ldev->pixel_clk);
|
||||
}
|
||||
|
||||
if (clk_prepare_enable(ldev->pixel_clk)) {
|
||||
DRM_ERROR("Unable to prepare pixel clock\n");
|
||||
drm_err(ddev, "Unable to prepare pixel clock\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -1939,7 +1940,7 @@ int ltdc_load(struct drm_device *ddev)
|
||||
if (panel) {
|
||||
bridge = drmm_panel_bridge_add(ddev, panel);
|
||||
if (IS_ERR(bridge)) {
|
||||
DRM_ERROR("panel-bridge endpoint %d\n", i);
|
||||
drm_err(ddev, "panel-bridge endpoint %d\n", i);
|
||||
ret = PTR_ERR(bridge);
|
||||
goto err;
|
||||
}
|
||||
@@ -1949,7 +1950,7 @@ int ltdc_load(struct drm_device *ddev)
|
||||
ret = ltdc_encoder_init(ddev, bridge);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
DRM_ERROR("init encoder endpoint %d\n", i);
|
||||
drm_err(ddev, "init encoder endpoint %d\n", i);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@@ -1967,29 +1968,29 @@ int ltdc_load(struct drm_device *ddev)
|
||||
|
||||
ldev->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(ldev->regs)) {
|
||||
DRM_ERROR("Unable to get ltdc registers\n");
|
||||
drm_err(ddev, "Unable to get ltdc registers\n");
|
||||
ret = PTR_ERR(ldev->regs);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ldev->regmap = devm_regmap_init_mmio(&pdev->dev, ldev->regs, &stm32_ltdc_regmap_cfg);
|
||||
if (IS_ERR(ldev->regmap)) {
|
||||
DRM_ERROR("Unable to regmap ltdc registers\n");
|
||||
drm_err(ddev, "Unable to regmap ltdc registers\n");
|
||||
ret = PTR_ERR(ldev->regmap);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ltdc_get_caps(ddev);
|
||||
if (ret) {
|
||||
DRM_ERROR("hardware identifier (0x%08x) not supported!\n",
|
||||
ldev->caps.hw_version);
|
||||
drm_err(ddev, "hardware identifier (0x%08x) not supported!\n",
|
||||
ldev->caps.hw_version);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Disable all interrupts */
|
||||
regmap_clear_bits(ldev->regmap, LTDC_IER, IER_MASK);
|
||||
|
||||
DRM_DEBUG_DRIVER("ltdc hw version 0x%08x\n", ldev->caps.hw_version);
|
||||
drm_dbg_driver(ddev, "ltdc hw version 0x%08x\n", ldev->caps.hw_version);
|
||||
|
||||
/* initialize default value for fifo underrun threshold & clear interrupt error counters */
|
||||
ldev->transfer_err = 0;
|
||||
@@ -2008,27 +2009,27 @@ int ltdc_load(struct drm_device *ddev)
|
||||
ltdc_irq_thread, IRQF_ONESHOT,
|
||||
dev_name(dev), ddev);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to register LTDC interrupt\n");
|
||||
drm_err(ddev, "Failed to register LTDC interrupt\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
crtc = drmm_kzalloc(ddev, sizeof(*crtc), GFP_KERNEL);
|
||||
if (!crtc) {
|
||||
DRM_ERROR("Failed to allocate crtc\n");
|
||||
drm_err(ddev, "Failed to allocate crtc\n");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ltdc_crtc_init(ddev, crtc);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to init crtc\n");
|
||||
drm_err(ddev, "Failed to init crtc\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = drm_vblank_init(ddev, NB_CRTC);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed calling drm_vblank_init()\n");
|
||||
drm_err(ddev, "Failed calling drm_vblank_init()\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -2047,7 +2048,7 @@ int ltdc_load(struct drm_device *ddev)
|
||||
|
||||
void ltdc_unload(struct drm_device *ddev)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
drm_dbg_driver(ddev, "\n");
|
||||
|
||||
pm_runtime_disable(ddev->dev);
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ int drm_sysfb_plane_helper_get_scanout_buffer(struct drm_plane *plane,
|
||||
struct drm_sysfb_crtc_state {
|
||||
struct drm_crtc_state base;
|
||||
|
||||
/* Primary-plane format; required for color mgmt. */
|
||||
/* CRTC input color format; required for color mgmt. */
|
||||
const struct drm_format_info *format;
|
||||
};
|
||||
|
||||
|
||||
@@ -210,7 +210,12 @@ int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
else if (!new_plane_state->visible)
|
||||
return 0;
|
||||
|
||||
if (new_fb->format != sysfb->fb_format) {
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc);
|
||||
|
||||
new_sysfb_crtc_state = to_drm_sysfb_crtc_state(new_crtc_state);
|
||||
new_sysfb_crtc_state->format = sysfb->fb_format;
|
||||
|
||||
if (new_fb->format != new_sysfb_crtc_state->format) {
|
||||
void *buf;
|
||||
|
||||
/* format conversion necessary; reserve buffer */
|
||||
@@ -220,11 +225,6 @@ int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc);
|
||||
|
||||
new_sysfb_crtc_state = to_drm_sysfb_crtc_state(new_crtc_state);
|
||||
new_sysfb_crtc_state->format = new_fb->format;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_sysfb_plane_helper_atomic_check);
|
||||
@@ -238,7 +238,10 @@ void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane, struct drm_at
|
||||
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
|
||||
struct drm_framebuffer *fb = plane_state->fb;
|
||||
unsigned int dst_pitch = sysfb->fb_pitch;
|
||||
const struct drm_format_info *dst_format = sysfb->fb_format;
|
||||
struct drm_crtc_state *crtc_state = crtc_state =
|
||||
drm_atomic_get_new_crtc_state(state, plane_state->crtc);
|
||||
struct drm_sysfb_crtc_state *sysfb_crtc_state = to_drm_sysfb_crtc_state(crtc_state);
|
||||
const struct drm_format_info *dst_format = sysfb_crtc_state->format;
|
||||
struct drm_atomic_helper_damage_iter iter;
|
||||
struct drm_rect damage;
|
||||
int ret, idx;
|
||||
@@ -370,16 +373,19 @@ EXPORT_SYMBOL(drm_sysfb_crtc_helper_atomic_check);
|
||||
|
||||
void drm_sysfb_crtc_reset(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_sysfb_device *sysfb = to_drm_sysfb_device(crtc->dev);
|
||||
struct drm_sysfb_crtc_state *sysfb_crtc_state;
|
||||
|
||||
if (crtc->state)
|
||||
drm_sysfb_crtc_state_destroy(to_drm_sysfb_crtc_state(crtc->state));
|
||||
|
||||
sysfb_crtc_state = kzalloc(sizeof(*sysfb_crtc_state), GFP_KERNEL);
|
||||
if (sysfb_crtc_state)
|
||||
if (sysfb_crtc_state) {
|
||||
sysfb_crtc_state->format = sysfb->fb_format;
|
||||
__drm_atomic_helper_crtc_reset(crtc, &sysfb_crtc_state->base);
|
||||
else
|
||||
} else {
|
||||
__drm_atomic_helper_crtc_reset(crtc, NULL);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_sysfb_crtc_reset);
|
||||
|
||||
|
||||
@@ -79,22 +79,19 @@ const struct drm_format_info *drm_sysfb_get_format_si(struct drm_device *dev,
|
||||
const struct screen_info *si)
|
||||
{
|
||||
const struct drm_format_info *format = NULL;
|
||||
u32 bits_per_pixel;
|
||||
struct pixel_format pixel;
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
bits_per_pixel = __screen_info_lfb_bits_per_pixel(si);
|
||||
ret = screen_info_pixel_format(si, &pixel);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < nformats; ++i) {
|
||||
const struct pixel_format *f = &formats[i].pixel;
|
||||
const struct drm_sysfb_format *f = &formats[i];
|
||||
|
||||
if (bits_per_pixel == f->bits_per_pixel &&
|
||||
si->red_size == f->red.length &&
|
||||
si->red_pos == f->red.offset &&
|
||||
si->green_size == f->green.length &&
|
||||
si->green_pos == f->green.offset &&
|
||||
si->blue_size == f->blue.length &&
|
||||
si->blue_pos == f->blue.offset) {
|
||||
format = drm_format_info(formats[i].fourcc);
|
||||
if (pixel_format_equal(&pixel, &f->pixel)) {
|
||||
format = drm_format_info(f->fourcc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ static const struct drm_format_info *vesadrm_get_format_si(struct drm_device *de
|
||||
{ PIXEL_FORMAT_RGB888, DRM_FORMAT_RGB888, },
|
||||
{ PIXEL_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888, },
|
||||
{ PIXEL_FORMAT_XBGR8888, DRM_FORMAT_XBGR8888, },
|
||||
{ PIXEL_FORMAT_C8, DRM_FORMAT_C8, },
|
||||
};
|
||||
|
||||
return drm_sysfb_get_format_si(dev, formats, ARRAY_SIZE(formats), si);
|
||||
@@ -82,7 +83,7 @@ static struct vesadrm_device *to_vesadrm_device(struct drm_device *dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* Palette
|
||||
* Color LUT
|
||||
*/
|
||||
|
||||
static void vesadrm_vga_cmap_write(struct vesadrm_device *vesa, unsigned int index,
|
||||
@@ -128,7 +129,7 @@ static void vesadrm_pmi_cmap_write(struct vesadrm_device *vesa, unsigned int ind
|
||||
}
|
||||
#endif
|
||||
|
||||
static void vesadrm_set_gamma_lut(struct drm_crtc *crtc, unsigned int index,
|
||||
static void vesadrm_set_color_lut(struct drm_crtc *crtc, unsigned int index,
|
||||
u16 red, u16 green, u16 blue)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
@@ -149,15 +150,15 @@ static void vesadrm_fill_gamma_lut(struct vesadrm_device *vesa,
|
||||
|
||||
switch (format->format) {
|
||||
case DRM_FORMAT_XRGB1555:
|
||||
drm_crtc_fill_gamma_555(crtc, vesadrm_set_gamma_lut);
|
||||
drm_crtc_fill_gamma_555(crtc, vesadrm_set_color_lut);
|
||||
break;
|
||||
case DRM_FORMAT_RGB565:
|
||||
drm_crtc_fill_gamma_565(crtc, vesadrm_set_gamma_lut);
|
||||
drm_crtc_fill_gamma_565(crtc, vesadrm_set_color_lut);
|
||||
break;
|
||||
case DRM_FORMAT_RGB888:
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_BGRX8888:
|
||||
drm_crtc_fill_gamma_888(crtc, vesadrm_set_gamma_lut);
|
||||
drm_crtc_fill_gamma_888(crtc, vesadrm_set_color_lut);
|
||||
break;
|
||||
default:
|
||||
drm_warn_once(dev, "Unsupported format %p4cc for gamma correction\n",
|
||||
@@ -175,15 +176,53 @@ static void vesadrm_load_gamma_lut(struct vesadrm_device *vesa,
|
||||
|
||||
switch (format->format) {
|
||||
case DRM_FORMAT_XRGB1555:
|
||||
drm_crtc_load_gamma_555_from_888(crtc, lut, vesadrm_set_gamma_lut);
|
||||
drm_crtc_load_gamma_555_from_888(crtc, lut, vesadrm_set_color_lut);
|
||||
break;
|
||||
case DRM_FORMAT_RGB565:
|
||||
drm_crtc_load_gamma_565_from_888(crtc, lut, vesadrm_set_gamma_lut);
|
||||
drm_crtc_load_gamma_565_from_888(crtc, lut, vesadrm_set_color_lut);
|
||||
break;
|
||||
case DRM_FORMAT_RGB888:
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_BGRX8888:
|
||||
drm_crtc_load_gamma_888(crtc, lut, vesadrm_set_gamma_lut);
|
||||
drm_crtc_load_gamma_888(crtc, lut, vesadrm_set_color_lut);
|
||||
break;
|
||||
default:
|
||||
drm_warn_once(dev, "Unsupported format %p4cc for gamma correction\n",
|
||||
&format->format);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void vesadrm_fill_palette_lut(struct vesadrm_device *vesa,
|
||||
const struct drm_format_info *format)
|
||||
{
|
||||
struct drm_device *dev = &vesa->sysfb.dev;
|
||||
struct drm_crtc *crtc = &vesa->crtc;
|
||||
|
||||
switch (format->format) {
|
||||
case DRM_FORMAT_C8:
|
||||
drm_crtc_fill_palette_8(crtc, vesadrm_set_color_lut);
|
||||
break;
|
||||
case DRM_FORMAT_RGB332:
|
||||
drm_crtc_fill_palette_332(crtc, vesadrm_set_color_lut);
|
||||
break;
|
||||
default:
|
||||
drm_warn_once(dev, "Unsupported format %p4cc for palette\n",
|
||||
&format->format);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void vesadrm_load_palette_lut(struct vesadrm_device *vesa,
|
||||
const struct drm_format_info *format,
|
||||
struct drm_color_lut *lut)
|
||||
{
|
||||
struct drm_device *dev = &vesa->sysfb.dev;
|
||||
struct drm_crtc *crtc = &vesa->crtc;
|
||||
|
||||
switch (format->format) {
|
||||
case DRM_FORMAT_C8:
|
||||
drm_crtc_load_palette_8(crtc, lut, vesadrm_set_color_lut);
|
||||
break;
|
||||
default:
|
||||
drm_warn_once(dev, "Unsupported format %p4cc for gamma correction\n",
|
||||
@@ -200,8 +239,67 @@ static const u64 vesadrm_primary_plane_format_modifiers[] = {
|
||||
DRM_SYSFB_PLANE_FORMAT_MODIFIERS,
|
||||
};
|
||||
|
||||
static int vesadrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
struct drm_atomic_state *new_state)
|
||||
{
|
||||
struct drm_sysfb_device *sysfb = to_drm_sysfb_device(plane->dev);
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane);
|
||||
struct drm_framebuffer *new_fb = new_plane_state->fb;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
struct drm_sysfb_crtc_state *new_sysfb_crtc_state;
|
||||
int ret;
|
||||
|
||||
ret = drm_sysfb_plane_helper_atomic_check(plane, new_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
else if (!new_plane_state->visible)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Fix up format conversion for specific cases
|
||||
*/
|
||||
|
||||
switch (sysfb->fb_format->format) {
|
||||
case DRM_FORMAT_C8:
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc);
|
||||
new_sysfb_crtc_state = to_drm_sysfb_crtc_state(new_crtc_state);
|
||||
|
||||
switch (new_fb->format->format) {
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
/*
|
||||
* Reduce XRGB8888 to RGB332. Each resulting pixel is an index
|
||||
* into the C8 hardware palette, which stores RGB332 colors.
|
||||
*/
|
||||
if (new_sysfb_crtc_state->format->format != DRM_FORMAT_RGB332) {
|
||||
new_sysfb_crtc_state->format =
|
||||
drm_format_info(DRM_FORMAT_RGB332);
|
||||
new_crtc_state->color_mgmt_changed = true;
|
||||
}
|
||||
break;
|
||||
case DRM_FORMAT_C8:
|
||||
/*
|
||||
* Restore original output. Emulation of XRGB8888 set RBG332
|
||||
* output format and hardware palette. This needs to be undone
|
||||
* when we switch back to DRM_FORMAT_C8.
|
||||
*/
|
||||
if (new_sysfb_crtc_state->format->format == DRM_FORMAT_RGB332) {
|
||||
new_sysfb_crtc_state->format = sysfb->fb_format;
|
||||
new_crtc_state->color_mgmt_changed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs vesadrm_primary_plane_helper_funcs = {
|
||||
DRM_SYSFB_PLANE_HELPER_FUNCS,
|
||||
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
|
||||
.atomic_check = vesadrm_primary_plane_helper_atomic_check,
|
||||
.atomic_update = drm_sysfb_plane_helper_atomic_update,
|
||||
.atomic_disable = drm_sysfb_plane_helper_atomic_disable,
|
||||
.get_scanout_buffer = drm_sysfb_plane_helper_get_scanout_buffer,
|
||||
};
|
||||
|
||||
static const struct drm_plane_funcs vesadrm_primary_plane_funcs = {
|
||||
@@ -223,15 +321,36 @@ static void vesadrm_crtc_helper_atomic_flush(struct drm_crtc *crtc,
|
||||
* plane's color format.
|
||||
*/
|
||||
if (crtc_state->enable && crtc_state->color_mgmt_changed) {
|
||||
if (sysfb_crtc_state->format == sysfb->fb_format) {
|
||||
if (crtc_state->gamma_lut)
|
||||
vesadrm_load_gamma_lut(vesa,
|
||||
sysfb_crtc_state->format,
|
||||
crtc_state->gamma_lut->data);
|
||||
else
|
||||
switch (sysfb->fb_format->format) {
|
||||
/*
|
||||
* Index formats
|
||||
*/
|
||||
case DRM_FORMAT_C8:
|
||||
if (sysfb_crtc_state->format->format == DRM_FORMAT_RGB332) {
|
||||
vesadrm_fill_palette_lut(vesa, sysfb_crtc_state->format);
|
||||
} else if (crtc->state->gamma_lut) {
|
||||
vesadrm_load_palette_lut(vesa,
|
||||
sysfb_crtc_state->format,
|
||||
crtc_state->gamma_lut->data);
|
||||
} else {
|
||||
vesadrm_fill_palette_lut(vesa, sysfb_crtc_state->format);
|
||||
}
|
||||
break;
|
||||
/*
|
||||
* Component formats
|
||||
*/
|
||||
default:
|
||||
if (sysfb_crtc_state->format == sysfb->fb_format) {
|
||||
if (crtc_state->gamma_lut)
|
||||
vesadrm_load_gamma_lut(vesa,
|
||||
sysfb_crtc_state->format,
|
||||
crtc_state->gamma_lut->data);
|
||||
else
|
||||
vesadrm_fill_gamma_lut(vesa, sysfb_crtc_state->format);
|
||||
} else {
|
||||
vesadrm_fill_gamma_lut(vesa, sysfb_crtc_state->format);
|
||||
} else {
|
||||
vesadrm_fill_gamma_lut(vesa, sysfb_crtc_state->format);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,9 +112,9 @@ struct i2c_hid {
|
||||
|
||||
struct i2chid_ops *ops;
|
||||
struct drm_panel_follower panel_follower;
|
||||
struct work_struct panel_follower_prepare_work;
|
||||
struct work_struct panel_follower_work;
|
||||
bool is_panel_follower;
|
||||
bool prepare_work_finished;
|
||||
bool panel_follower_work_finished;
|
||||
};
|
||||
|
||||
static const struct i2c_hid_quirks {
|
||||
@@ -1110,10 +1110,10 @@ static int i2c_hid_core_probe_panel_follower(struct i2c_hid *ihid)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ihid_core_panel_prepare_work(struct work_struct *work)
|
||||
static void ihid_core_panel_follower_work(struct work_struct *work)
|
||||
{
|
||||
struct i2c_hid *ihid = container_of(work, struct i2c_hid,
|
||||
panel_follower_prepare_work);
|
||||
panel_follower_work);
|
||||
struct hid_device *hid = ihid->hid;
|
||||
int ret;
|
||||
|
||||
@@ -1130,7 +1130,7 @@ static void ihid_core_panel_prepare_work(struct work_struct *work)
|
||||
if (ret)
|
||||
dev_warn(&ihid->client->dev, "Power on failed: %d\n", ret);
|
||||
else
|
||||
WRITE_ONCE(ihid->prepare_work_finished, true);
|
||||
WRITE_ONCE(ihid->panel_follower_work_finished, true);
|
||||
|
||||
/*
|
||||
* The work APIs provide a number of memory ordering guarantees
|
||||
@@ -1139,12 +1139,12 @@ static void ihid_core_panel_prepare_work(struct work_struct *work)
|
||||
* guarantee that a write that happened in the work is visible after
|
||||
* cancel_work_sync(). We'll add a write memory barrier here to match
|
||||
* with i2c_hid_core_panel_unpreparing() to ensure that our write to
|
||||
* prepare_work_finished is visible there.
|
||||
* panel_follower_work_finished is visible there.
|
||||
*/
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
static int i2c_hid_core_panel_prepared(struct drm_panel_follower *follower)
|
||||
static int i2c_hid_core_panel_follower_resume(struct drm_panel_follower *follower)
|
||||
{
|
||||
struct i2c_hid *ihid = container_of(follower, struct i2c_hid, panel_follower);
|
||||
|
||||
@@ -1152,29 +1152,36 @@ static int i2c_hid_core_panel_prepared(struct drm_panel_follower *follower)
|
||||
* Powering on a touchscreen can be a slow process. Queue the work to
|
||||
* the system workqueue so we don't block the panel's power up.
|
||||
*/
|
||||
WRITE_ONCE(ihid->prepare_work_finished, false);
|
||||
schedule_work(&ihid->panel_follower_prepare_work);
|
||||
WRITE_ONCE(ihid->panel_follower_work_finished, false);
|
||||
schedule_work(&ihid->panel_follower_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_hid_core_panel_unpreparing(struct drm_panel_follower *follower)
|
||||
static int i2c_hid_core_panel_follower_suspend(struct drm_panel_follower *follower)
|
||||
{
|
||||
struct i2c_hid *ihid = container_of(follower, struct i2c_hid, panel_follower);
|
||||
|
||||
cancel_work_sync(&ihid->panel_follower_prepare_work);
|
||||
cancel_work_sync(&ihid->panel_follower_work);
|
||||
|
||||
/* Match with ihid_core_panel_prepare_work() */
|
||||
/* Match with ihid_core_panel_follower_work() */
|
||||
smp_rmb();
|
||||
if (!READ_ONCE(ihid->prepare_work_finished))
|
||||
if (!READ_ONCE(ihid->panel_follower_work_finished))
|
||||
return 0;
|
||||
|
||||
return i2c_hid_core_suspend(ihid, true);
|
||||
}
|
||||
|
||||
static const struct drm_panel_follower_funcs i2c_hid_core_panel_follower_funcs = {
|
||||
.panel_prepared = i2c_hid_core_panel_prepared,
|
||||
.panel_unpreparing = i2c_hid_core_panel_unpreparing,
|
||||
static const struct drm_panel_follower_funcs
|
||||
i2c_hid_core_panel_follower_prepare_funcs = {
|
||||
.panel_prepared = i2c_hid_core_panel_follower_resume,
|
||||
.panel_unpreparing = i2c_hid_core_panel_follower_suspend,
|
||||
};
|
||||
|
||||
static const struct drm_panel_follower_funcs
|
||||
i2c_hid_core_panel_follower_enable_funcs = {
|
||||
.panel_enabled = i2c_hid_core_panel_follower_resume,
|
||||
.panel_disabling = i2c_hid_core_panel_follower_suspend,
|
||||
};
|
||||
|
||||
static int i2c_hid_core_register_panel_follower(struct i2c_hid *ihid)
|
||||
@@ -1182,7 +1189,10 @@ static int i2c_hid_core_register_panel_follower(struct i2c_hid *ihid)
|
||||
struct device *dev = &ihid->client->dev;
|
||||
int ret;
|
||||
|
||||
ihid->panel_follower.funcs = &i2c_hid_core_panel_follower_funcs;
|
||||
if (ihid->hid->initial_quirks & HID_QUIRK_POWER_ON_AFTER_BACKLIGHT)
|
||||
ihid->panel_follower.funcs = &i2c_hid_core_panel_follower_enable_funcs;
|
||||
else
|
||||
ihid->panel_follower.funcs = &i2c_hid_core_panel_follower_prepare_funcs;
|
||||
|
||||
/*
|
||||
* If we're not in control of our own power up/power down then we can't
|
||||
@@ -1237,7 +1247,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
|
||||
init_waitqueue_head(&ihid->wait);
|
||||
mutex_init(&ihid->cmd_lock);
|
||||
mutex_init(&ihid->reset_lock);
|
||||
INIT_WORK(&ihid->panel_follower_prepare_work, ihid_core_panel_prepare_work);
|
||||
INIT_WORK(&ihid->panel_follower_work, ihid_core_panel_follower_work);
|
||||
|
||||
/* we need to allocate the command buffer without knowing the maximum
|
||||
* size of the reports. Let's use HID_MIN_BUFFER_SIZE, then we do the
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@@ -23,6 +24,7 @@ struct elan_i2c_hid_chip_data {
|
||||
unsigned int post_power_delay_ms;
|
||||
u16 hid_descriptor_address;
|
||||
const char *main_supply_name;
|
||||
bool power_after_backlight;
|
||||
};
|
||||
|
||||
struct i2c_hid_of_elan {
|
||||
@@ -97,6 +99,7 @@ static int i2c_hid_of_elan_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_hid_of_elan *ihid_elan;
|
||||
int ret;
|
||||
u32 quirks = 0;
|
||||
|
||||
ihid_elan = devm_kzalloc(&client->dev, sizeof(*ihid_elan), GFP_KERNEL);
|
||||
if (!ihid_elan)
|
||||
@@ -131,8 +134,12 @@ static int i2c_hid_of_elan_probe(struct i2c_client *client)
|
||||
}
|
||||
}
|
||||
|
||||
if (ihid_elan->chip_data->power_after_backlight)
|
||||
quirks = HID_QUIRK_POWER_ON_AFTER_BACKLIGHT;
|
||||
|
||||
ret = i2c_hid_core_probe(client, &ihid_elan->ops,
|
||||
ihid_elan->chip_data->hid_descriptor_address, 0);
|
||||
ihid_elan->chip_data->hid_descriptor_address,
|
||||
quirks);
|
||||
if (ret)
|
||||
goto err_deassert_reset;
|
||||
|
||||
@@ -150,6 +157,7 @@ static const struct elan_i2c_hid_chip_data elan_ekth6915_chip_data = {
|
||||
.post_gpio_reset_on_delay_ms = 300,
|
||||
.hid_descriptor_address = 0x0001,
|
||||
.main_supply_name = "vcc33",
|
||||
.power_after_backlight = true,
|
||||
};
|
||||
|
||||
static const struct elan_i2c_hid_chip_data elan_ekth6a12nay_chip_data = {
|
||||
@@ -157,6 +165,7 @@ static const struct elan_i2c_hid_chip_data elan_ekth6a12nay_chip_data = {
|
||||
.post_gpio_reset_on_delay_ms = 300,
|
||||
.hid_descriptor_address = 0x0001,
|
||||
.main_supply_name = "vcc33",
|
||||
.power_after_backlight = true,
|
||||
};
|
||||
|
||||
static const struct elan_i2c_hid_chip_data ilitek_ili9882t_chip_data = {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <video/pixel_format.h>
|
||||
|
||||
static void resource_init_named(struct resource *r,
|
||||
resource_size_t start, resource_size_t size,
|
||||
const char *name, unsigned int flags)
|
||||
@@ -180,3 +182,56 @@ u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si)
|
||||
return bits_per_pixel;
|
||||
}
|
||||
EXPORT_SYMBOL(__screen_info_lfb_bits_per_pixel);
|
||||
|
||||
static int __screen_info_lfb_pixel_format(const struct screen_info *si, struct pixel_format *f)
|
||||
{
|
||||
u32 bits_per_pixel = __screen_info_lfb_bits_per_pixel(si);
|
||||
|
||||
if (bits_per_pixel > U8_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
f->bits_per_pixel = bits_per_pixel;
|
||||
|
||||
if (si->lfb_depth > 8) {
|
||||
f->indexed = false;
|
||||
f->alpha.offset = 0;
|
||||
f->alpha.length = 0;
|
||||
f->red.offset = si->red_pos;
|
||||
f->red.length = si->red_size;
|
||||
f->green.offset = si->green_pos;
|
||||
f->green.length = si->green_size;
|
||||
f->blue.offset = si->blue_pos;
|
||||
f->blue.length = si->blue_size;
|
||||
} else {
|
||||
f->indexed = true;
|
||||
f->index.offset = 0;
|
||||
f->index.length = si->lfb_depth;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* screen_info_pixel_format - Returns the screen-info format as pixel-format description
|
||||
*
|
||||
* @si: the screen_info
|
||||
* @f: pointer to return pixel-format description
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, or a negative errno code otherwise.
|
||||
*/
|
||||
int screen_info_pixel_format(const struct screen_info *si, struct pixel_format *f)
|
||||
{
|
||||
unsigned int type = screen_info_video_type(si);
|
||||
|
||||
/* TODO: Add support for additional types as needed. */
|
||||
switch (type) {
|
||||
case VIDEO_TYPE_VLFB:
|
||||
case VIDEO_TYPE_EFI:
|
||||
return __screen_info_lfb_pixel_format(si, f);
|
||||
}
|
||||
|
||||
/* not supported */
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(screen_info_pixel_format);
|
||||
|
||||
@@ -143,6 +143,7 @@ void drm_crtc_fill_gamma_555(struct drm_crtc *crtc, drm_crtc_set_lut_func set_ga
|
||||
void drm_crtc_load_palette_8(struct drm_crtc *crtc, const struct drm_color_lut *lut,
|
||||
drm_crtc_set_lut_func set_palette);
|
||||
|
||||
void drm_crtc_fill_palette_332(struct drm_crtc *crtc, drm_crtc_set_lut_func set_palette);
|
||||
void drm_crtc_fill_palette_8(struct drm_crtc *crtc, drm_crtc_set_lut_func set_palette);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -160,6 +160,20 @@ struct drm_panel_follower_funcs {
|
||||
* Called before the panel is powered off.
|
||||
*/
|
||||
int (*panel_unpreparing)(struct drm_panel_follower *follower);
|
||||
|
||||
/**
|
||||
* @panel_enabled:
|
||||
*
|
||||
* Called after the panel and the backlight have been enabled.
|
||||
*/
|
||||
int (*panel_enabled)(struct drm_panel_follower *follower);
|
||||
|
||||
/**
|
||||
* @panel_disabling:
|
||||
*
|
||||
* Called before the panel and the backlight are disabled.
|
||||
*/
|
||||
int (*panel_disabling)(struct drm_panel_follower *follower);
|
||||
};
|
||||
|
||||
struct drm_panel_follower {
|
||||
|
||||
@@ -364,6 +364,7 @@ struct hid_item {
|
||||
* | @HID_QUIRK_HAVE_SPECIAL_DRIVER:
|
||||
* | @HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE:
|
||||
* | @HID_QUIRK_IGNORE_SPECIAL_DRIVER
|
||||
* | @HID_QUIRK_POWER_ON_AFTER_BACKLIGHT
|
||||
* | @HID_QUIRK_FULLSPEED_INTERVAL:
|
||||
* | @HID_QUIRK_NO_INIT_REPORTS:
|
||||
* | @HID_QUIRK_NO_IGNORE:
|
||||
@@ -391,6 +392,7 @@ struct hid_item {
|
||||
#define HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE BIT(20)
|
||||
#define HID_QUIRK_NOINVERT BIT(21)
|
||||
#define HID_QUIRK_IGNORE_SPECIAL_DRIVER BIT(22)
|
||||
#define HID_QUIRK_POWER_ON_AFTER_BACKLIGHT BIT(23)
|
||||
#define HID_QUIRK_FULLSPEED_INTERVAL BIT(28)
|
||||
#define HID_QUIRK_NO_INIT_REPORTS BIT(29)
|
||||
#define HID_QUIRK_NO_IGNORE BIT(30)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define SCREEN_INFO_MAX_RESOURCES 3
|
||||
|
||||
struct pci_dev;
|
||||
struct pixel_format;
|
||||
struct resource;
|
||||
|
||||
static inline bool __screen_info_has_lfb(unsigned int type)
|
||||
@@ -136,6 +137,7 @@ static inline u32 __screen_info_vesapm_info_base(const struct screen_info *si)
|
||||
ssize_t screen_info_resources(const struct screen_info *si, struct resource *r, size_t num);
|
||||
|
||||
u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
|
||||
int screen_info_pixel_format(const struct screen_info *si, struct pixel_format *f);
|
||||
|
||||
#if defined(CONFIG_PCI)
|
||||
void screen_info_apply_fixups(void);
|
||||
|
||||
@@ -20,6 +20,9 @@ struct pixel_format {
|
||||
};
|
||||
};
|
||||
|
||||
#define PIXEL_FORMAT_C8 \
|
||||
{ 8, true, { .index = {0, 8}, } }
|
||||
|
||||
#define PIXEL_FORMAT_XRGB1555 \
|
||||
{ 16, false, { .alpha = {0, 0}, .red = {10, 5}, .green = {5, 5}, .blue = {0, 5} } }
|
||||
|
||||
@@ -38,4 +41,62 @@ struct pixel_format {
|
||||
#define PIXEL_FORMAT_XRGB2101010 \
|
||||
{ 32, false, { .alpha = {0, 0}, .red = {20, 10}, .green = {10, 10}, .blue = {0, 10} } }
|
||||
|
||||
#define __pixel_format_cmp_field(lhs, rhs, name) \
|
||||
{ \
|
||||
int ret = ((lhs)->name) - ((rhs)->name); \
|
||||
if (ret) \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define __pixel_format_cmp_bitfield(lhs, rhs, name) \
|
||||
{ \
|
||||
__pixel_format_cmp_field(lhs, rhs, name.offset); \
|
||||
__pixel_format_cmp_field(lhs, rhs, name.length); \
|
||||
}
|
||||
|
||||
/**
|
||||
* pixel_format_cmp - Compares two pixel-format descriptions
|
||||
*
|
||||
* @lhs: a pixel-format description
|
||||
* @rhs: a pixel-format description
|
||||
*
|
||||
* Compares two pixel-format descriptions for their order. The semantics
|
||||
* are equivalent to memcmp().
|
||||
*
|
||||
* Returns:
|
||||
* 0 if both arguments describe the same pixel format, less-than-zero if lhs < rhs,
|
||||
* or greater-than-zero if lhs > rhs.
|
||||
*/
|
||||
static inline int pixel_format_cmp(const struct pixel_format *lhs, const struct pixel_format *rhs)
|
||||
{
|
||||
__pixel_format_cmp_field(lhs, rhs, bits_per_pixel);
|
||||
__pixel_format_cmp_field(lhs, rhs, indexed);
|
||||
|
||||
if (lhs->indexed) {
|
||||
__pixel_format_cmp_bitfield(lhs, rhs, index);
|
||||
} else {
|
||||
__pixel_format_cmp_bitfield(lhs, rhs, alpha);
|
||||
__pixel_format_cmp_bitfield(lhs, rhs, red);
|
||||
__pixel_format_cmp_bitfield(lhs, rhs, green);
|
||||
__pixel_format_cmp_bitfield(lhs, rhs, blue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pixel_format_equal - Compares two pixel-format descriptions for equality
|
||||
*
|
||||
* @lhs: a pixel-format description
|
||||
* @rhs: a pixel-format description
|
||||
*
|
||||
* Returns:
|
||||
* True if both arguments describe the same pixel format, or false otherwise.
|
||||
*/
|
||||
static inline bool pixel_format_equal(const struct pixel_format *lhs,
|
||||
const struct pixel_format *rhs)
|
||||
{
|
||||
return !pixel_format_cmp(lhs, rhs);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user