mirror of
https://github.com/torvalds/linux.git
synced 2024-10-26 15:02:39 +00:00
drm-misc-next for 5.8:
UAPI Changes: Cross-subsystem Changes: * dma-buf: use atomic64_fetch_add() for context id * Documentation: document bindings for ASUS ZOOT TM5P5, BOE NV133FHM-N62, hpd-gpios Core Changes: Driver Changes: * drm/ast: fix supend; cleanups * drm/i2c: cleanups * drm/panel: add MODULE_LICENSE to panel-visinox-rm69299; add support for ASUS TM5P5i, BOE NV133FHM-N62i; fix size and bpp of BOE NV133FHM-N61 add hpd-gpio to panel-simple * drm/mcde: fix return value check in mcde_dsi_bind() * drm/mgag200: use managed drmm_mode_config_init(); cleanups * fbdev/pxa168fb: cleanups -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEchf7rIzpz2NEoWjlaA3BHVMLeiMFAl687Z0ACgkQaA3BHVML eiMp+AgAvjbwyD2v1HSFxx5B0bYSzO29Gaq6zPb5xieINAeeKLRwUamIvJH55YST p/O9Lpio8yomB8AhM1w3GkrkD3YLJ4N9ABiKEU21JV09r1qLPksAZtm1IYnMfMiY fjz5Y1B+OBTDzNSrBzDRNQrOsT5wcWXbwuC2S69nW5CIXBzkzUuE9KLv+vM3jvSd QWLEHjodhg2W+4gClcSz1W1aYaSpeytNgL/cIn+dF0dOOJYj4AQ8SvC0YHJakmBL jNmCsXKm7Kfuk7MLhIruIww+2SVWgjOoNWz1E86IAbjHMSfrIKcl/pvAjS5uXSVp gKgFF7H7RnY+g/25DiIsoDfws5cOYg== =IitK -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2020-05-14' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for 5.8: UAPI Changes: Cross-subsystem Changes: * dma-buf: use atomic64_fetch_add() for context id * Documentation: document bindings for ASUS ZOOT TM5P5, BOE NV133FHM-N62, hpd-gpios Core Changes: Driver Changes: * drm/ast: fix supend; cleanups * drm/i2c: cleanups * drm/panel: add MODULE_LICENSE to panel-visinox-rm69299; add support for ASUS TM5P5i, BOE NV133FHM-N62i; fix size and bpp of BOE NV133FHM-N61 add hpd-gpio to panel-simple * drm/mcde: fix return value check in mcde_dsi_bind() * drm/mgag200: use managed drmm_mode_config_init(); cleanups * fbdev/pxa168fb: cleanups Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200514070819.GA6930@linux-uq9g
This commit is contained in:
commit
1493bddcca
|
@ -0,0 +1,56 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/asus,z00t-tm5p5-nt35596.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ASUS Z00T TM5P5 NT35596 5.5" 1080×1920 LCD Panel
|
||||
|
||||
maintainers:
|
||||
- Konrad Dybcio <konradybcio@gmail.com>
|
||||
|
||||
description: |+
|
||||
This panel seems to only be found in the Asus Z00T
|
||||
smartphone and we have no straightforward way of
|
||||
actually getting the correct model number,
|
||||
as no schematics are released publicly.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: asus,z00t-tm5p5-n35596
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
vdd-supply:
|
||||
description: core voltage supply
|
||||
vddio-supply:
|
||||
description: vddio supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- vddio-supply
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
reg = <0>;
|
||||
|
||||
compatible = "asus,z00t-tm5p5-n35596";
|
||||
|
||||
vdd-supply = <&pm8916_l8>;
|
||||
vddio-supply = <&pm8916_l6>;
|
||||
reset-gpios = <&msmgpio 25 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
|
@ -96,6 +96,12 @@ properties:
|
|||
(hot plug detect) signal, but the signal isn't hooked up so we should
|
||||
hardcode the max delay from the panel spec when powering up the panel.
|
||||
|
||||
hpd-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
If Hot Plug Detect (HPD) is connected to a GPIO in the system rather
|
||||
than a dedicated HPD pin the pin can be specified here.
|
||||
|
||||
# Control I/Os
|
||||
|
||||
# Many display panels can be controlled through pins driven by GPIOs. The nature
|
||||
|
|
|
@ -75,6 +75,8 @@ properties:
|
|||
- boe,nv101wxmn51
|
||||
# BOE NV133FHM-N61 13.3" FHD (1920x1080) TFT LCD Panel
|
||||
- boe,nv133fhm-n61
|
||||
# BOE NV133FHM-N62 13.3" FHD (1920x1080) TFT LCD Panel
|
||||
- boe,nv133fhm-n62
|
||||
# BOE NV140FHM-N49 14.0" FHD a-Si FT panel
|
||||
- boe,nv140fhmn49
|
||||
# CDTech(H.K.) Electronics Limited 4.3" 480x272 color TFT-LCD panel
|
||||
|
|
|
@ -106,7 +106,7 @@ EXPORT_SYMBOL(dma_fence_get_stub);
|
|||
u64 dma_fence_context_alloc(unsigned num)
|
||||
{
|
||||
WARN_ON(!num);
|
||||
return atomic64_add_return(num, &dma_fence_context_counter) - num;
|
||||
return atomic64_fetch_add(num, &dma_fence_context_counter);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_context_alloc);
|
||||
|
||||
|
|
|
@ -561,8 +561,9 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
static void
|
||||
ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct ast_private *ast = plane->dev->dev_private;
|
||||
struct drm_plane_state *state = plane->state;
|
||||
|
@ -801,6 +802,9 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!state->enable)
|
||||
return 0; /* no mode checks if CRTC is being disabled */
|
||||
|
||||
ast_state = to_ast_crtc_state(state);
|
||||
|
||||
format = ast_state->format;
|
||||
|
|
|
@ -1133,7 +1133,8 @@ static void tda998x_audio_shutdown(struct device *dev, void *data)
|
|||
mutex_unlock(&priv->audio_mutex);
|
||||
}
|
||||
|
||||
int tda998x_audio_digital_mute(struct device *dev, void *data, bool enable)
|
||||
static int tda998x_audio_digital_mute(struct device *dev, void *data,
|
||||
bool enable)
|
||||
{
|
||||
struct tda998x_priv *priv = dev_get_drvdata(dev);
|
||||
|
||||
|
|
|
@ -1073,10 +1073,9 @@ static int mcde_dsi_bind(struct device *dev, struct device *master,
|
|||
panel = NULL;
|
||||
|
||||
bridge = of_drm_find_bridge(child);
|
||||
if (IS_ERR(bridge)) {
|
||||
dev_err(dev, "failed to find bridge (%ld)\n",
|
||||
PTR_ERR(bridge));
|
||||
return PTR_ERR(bridge);
|
||||
if (!bridge) {
|
||||
dev_err(dev, "failed to find bridge\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -260,7 +260,7 @@ int mgag200_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
|
|||
uint32_t handle, uint32_t width, uint32_t height)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = (struct mga_device *)dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_gem_vram_object *gbo = NULL;
|
||||
int ret;
|
||||
|
@ -307,7 +307,7 @@ err_drm_gem_object_put_unlocked:
|
|||
|
||||
int mgag200_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
||||
{
|
||||
struct mga_device *mdev = (struct mga_device *)crtc->dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(crtc->dev);
|
||||
|
||||
/* Our origin is at (64,64) */
|
||||
x += 64;
|
||||
|
|
|
@ -120,7 +120,7 @@ int mgag200_driver_dumb_create(struct drm_file *file,
|
|||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
unsigned long pg_align;
|
||||
|
||||
if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
|
||||
|
|
|
@ -104,11 +104,6 @@ struct mga_crtc {
|
|||
bool enabled;
|
||||
};
|
||||
|
||||
struct mga_mode_info {
|
||||
bool mode_config_initialized;
|
||||
struct mga_crtc *crtc;
|
||||
};
|
||||
|
||||
struct mga_i2c_chan {
|
||||
struct i2c_adapter adapter;
|
||||
struct drm_device *dev;
|
||||
|
@ -160,17 +155,14 @@ struct mga_device {
|
|||
void __iomem *rmmio;
|
||||
|
||||
struct mga_mc mc;
|
||||
struct mga_mode_info mode_info;
|
||||
|
||||
struct mga_cursor cursor;
|
||||
|
||||
size_t vram_fb_available;
|
||||
|
||||
bool suspended;
|
||||
int num_crtc;
|
||||
enum mga_type type;
|
||||
int has_sdram;
|
||||
struct drm_display_mode mode;
|
||||
|
||||
int bpp_shifts[4];
|
||||
|
||||
|
@ -179,9 +171,15 @@ struct mga_device {
|
|||
/* SE model number stored in reg 0x1e24 */
|
||||
u32 unique_rev_id;
|
||||
|
||||
struct mga_connector connector;
|
||||
struct drm_encoder encoder;
|
||||
};
|
||||
|
||||
static inline struct mga_device *to_mga_device(struct drm_device *dev)
|
||||
{
|
||||
return dev->dev_private;
|
||||
}
|
||||
|
||||
static inline enum mga_type
|
||||
mgag200_type_from_driver_data(kernel_ulong_t driver_data)
|
||||
{
|
||||
|
@ -196,7 +194,6 @@ mgag200_flags_from_driver_data(kernel_ulong_t driver_data)
|
|||
|
||||
/* mgag200_mode.c */
|
||||
int mgag200_modeset_init(struct mga_device *mdev);
|
||||
void mgag200_modeset_fini(struct mga_device *mdev);
|
||||
|
||||
/* mgag200_main.c */
|
||||
int mgag200_driver_load(struct drm_device *dev, unsigned long flags);
|
||||
|
|
|
@ -61,34 +61,34 @@ static inline void mga_i2c_set(struct mga_device *mdev, int mask, int state)
|
|||
static void mga_gpio_setsda(void *data, int state)
|
||||
{
|
||||
struct mga_i2c_chan *i2c = data;
|
||||
struct mga_device *mdev = i2c->dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(i2c->dev);
|
||||
mga_i2c_set(mdev, i2c->data, state);
|
||||
}
|
||||
|
||||
static void mga_gpio_setscl(void *data, int state)
|
||||
{
|
||||
struct mga_i2c_chan *i2c = data;
|
||||
struct mga_device *mdev = i2c->dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(i2c->dev);
|
||||
mga_i2c_set(mdev, i2c->clock, state);
|
||||
}
|
||||
|
||||
static int mga_gpio_getsda(void *data)
|
||||
{
|
||||
struct mga_i2c_chan *i2c = data;
|
||||
struct mga_device *mdev = i2c->dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(i2c->dev);
|
||||
return (mga_i2c_read_gpio(mdev) & i2c->data) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int mga_gpio_getscl(void *data)
|
||||
{
|
||||
struct mga_i2c_chan *i2c = data;
|
||||
struct mga_device *mdev = i2c->dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(i2c->dev);
|
||||
return (mga_i2c_read_gpio(mdev) & i2c->clock) ? 1 : 0;
|
||||
}
|
||||
|
||||
struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev)
|
||||
{
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
struct mga_i2c_chan *i2c;
|
||||
int ret;
|
||||
int data, clock;
|
||||
|
|
|
@ -10,15 +10,8 @@
|
|||
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
|
||||
#include "mgag200_drv.h"
|
||||
|
||||
static const struct drm_mode_config_funcs mga_mode_funcs = {
|
||||
.fb_create = drm_gem_fb_create
|
||||
};
|
||||
|
||||
static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem)
|
||||
{
|
||||
int offset;
|
||||
|
@ -66,51 +59,54 @@ static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem)
|
|||
/* Map the framebuffer from the card and configure the core */
|
||||
static int mga_vram_init(struct mga_device *mdev)
|
||||
{
|
||||
struct drm_device *dev = mdev->dev;
|
||||
void __iomem *mem;
|
||||
|
||||
/* BAR 0 is VRAM */
|
||||
mdev->mc.vram_base = pci_resource_start(mdev->dev->pdev, 0);
|
||||
mdev->mc.vram_window = pci_resource_len(mdev->dev->pdev, 0);
|
||||
mdev->mc.vram_base = pci_resource_start(dev->pdev, 0);
|
||||
mdev->mc.vram_window = pci_resource_len(dev->pdev, 0);
|
||||
|
||||
if (!devm_request_mem_region(mdev->dev->dev, mdev->mc.vram_base, mdev->mc.vram_window,
|
||||
"mgadrmfb_vram")) {
|
||||
if (!devm_request_mem_region(dev->dev, mdev->mc.vram_base,
|
||||
mdev->mc.vram_window, "mgadrmfb_vram")) {
|
||||
DRM_ERROR("can't reserve VRAM\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
mem = pci_iomap(mdev->dev->pdev, 0, 0);
|
||||
mem = pci_iomap(dev->pdev, 0, 0);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
|
||||
mdev->mc.vram_size = mga_probe_vram(mdev, mem);
|
||||
|
||||
pci_iounmap(mdev->dev->pdev, mem);
|
||||
pci_iounmap(dev->pdev, mem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mgag200_device_init(struct drm_device *dev,
|
||||
uint32_t flags)
|
||||
int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mga_device *mdev;
|
||||
int ret, option;
|
||||
|
||||
mdev = devm_kzalloc(dev->dev, sizeof(struct mga_device), GFP_KERNEL);
|
||||
if (mdev == NULL)
|
||||
return -ENOMEM;
|
||||
dev->dev_private = (void *)mdev;
|
||||
mdev->dev = dev;
|
||||
|
||||
mdev->flags = mgag200_flags_from_driver_data(flags);
|
||||
mdev->type = mgag200_type_from_driver_data(flags);
|
||||
|
||||
/* Hardcode the number of CRTCs to 1 */
|
||||
mdev->num_crtc = 1;
|
||||
|
||||
pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, &option);
|
||||
mdev->has_sdram = !(option & (1 << 14));
|
||||
|
||||
/* BAR 0 is the framebuffer, BAR 1 contains registers */
|
||||
mdev->rmmio_base = pci_resource_start(mdev->dev->pdev, 1);
|
||||
mdev->rmmio_size = pci_resource_len(mdev->dev->pdev, 1);
|
||||
mdev->rmmio_base = pci_resource_start(dev->pdev, 1);
|
||||
mdev->rmmio_size = pci_resource_len(dev->pdev, 1);
|
||||
|
||||
if (!devm_request_mem_region(mdev->dev->dev, mdev->rmmio_base, mdev->rmmio_size,
|
||||
"mgadrmfb_mmio")) {
|
||||
DRM_ERROR("can't reserve mmio registers\n");
|
||||
if (!devm_request_mem_region(dev->dev, mdev->rmmio_base,
|
||||
mdev->rmmio_size, "mgadrmfb_mmio")) {
|
||||
drm_err(dev, "can't reserve mmio registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -121,86 +117,43 @@ static int mgag200_device_init(struct drm_device *dev,
|
|||
/* stash G200 SE model number for later use */
|
||||
if (IS_G200_SE(mdev)) {
|
||||
mdev->unique_rev_id = RREG32(0x1e24);
|
||||
DRM_DEBUG("G200 SE unique revision id is 0x%x\n",
|
||||
mdev->unique_rev_id);
|
||||
drm_dbg(dev, "G200 SE unique revision id is 0x%x\n",
|
||||
mdev->unique_rev_id);
|
||||
}
|
||||
|
||||
ret = mga_vram_init(mdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mdev->bpp_shifts[0] = 0;
|
||||
mdev->bpp_shifts[1] = 1;
|
||||
mdev->bpp_shifts[2] = 0;
|
||||
mdev->bpp_shifts[3] = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions here will be called by the core once it's bound the driver to
|
||||
* a PCI device
|
||||
*/
|
||||
|
||||
|
||||
int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
struct mga_device *mdev;
|
||||
int r;
|
||||
|
||||
mdev = devm_kzalloc(dev->dev, sizeof(struct mga_device), GFP_KERNEL);
|
||||
if (mdev == NULL)
|
||||
return -ENOMEM;
|
||||
dev->dev_private = (void *)mdev;
|
||||
mdev->dev = dev;
|
||||
|
||||
r = mgag200_device_init(dev, flags);
|
||||
if (r) {
|
||||
dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
r = mgag200_mm_init(mdev);
|
||||
if (r)
|
||||
ret = mgag200_mm_init(mdev);
|
||||
if (ret)
|
||||
goto err_mm;
|
||||
|
||||
drm_mode_config_init(dev);
|
||||
dev->mode_config.funcs = (void *)&mga_mode_funcs;
|
||||
if (IS_G200_SE(mdev) && mdev->vram_fb_available < (2048*1024))
|
||||
dev->mode_config.preferred_depth = 16;
|
||||
else
|
||||
dev->mode_config.preferred_depth = 32;
|
||||
dev->mode_config.prefer_shadow = 1;
|
||||
|
||||
r = mgag200_modeset_init(mdev);
|
||||
if (r) {
|
||||
dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
|
||||
goto err_modeset;
|
||||
ret = mgag200_modeset_init(mdev);
|
||||
if (ret) {
|
||||
drm_err(dev, "Fatal error during modeset init: %d\n", ret);
|
||||
goto err_mgag200_mm_fini;
|
||||
}
|
||||
|
||||
r = mgag200_cursor_init(mdev);
|
||||
if (r)
|
||||
dev_warn(&dev->pdev->dev,
|
||||
"Could not initialize cursors. Not doing hardware cursors.\n");
|
||||
ret = mgag200_cursor_init(mdev);
|
||||
if (ret)
|
||||
drm_err(dev, "Could not initialize cursors. Not doing hardware cursors.\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_modeset:
|
||||
drm_mode_config_cleanup(dev);
|
||||
mgag200_cursor_fini(mdev);
|
||||
err_mgag200_mm_fini:
|
||||
mgag200_mm_fini(mdev);
|
||||
err_mm:
|
||||
dev->dev_private = NULL;
|
||||
|
||||
return r;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mgag200_driver_unload(struct drm_device *dev)
|
||||
{
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
|
||||
if (mdev == NULL)
|
||||
return;
|
||||
mgag200_modeset_fini(mdev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
mgag200_cursor_fini(mdev);
|
||||
mgag200_mm_fini(mdev);
|
||||
dev->dev_private = NULL;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
@ -28,7 +29,7 @@
|
|||
static void mga_crtc_load_lut(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
struct drm_framebuffer *fb = crtc->primary->fb;
|
||||
u16 *r_ptr, *g_ptr, *b_ptr;
|
||||
int i;
|
||||
|
@ -728,7 +729,7 @@ static int mga_crtc_set_plls(struct mga_device *mdev, long clock)
|
|||
|
||||
static void mga_g200wb_prepare(struct drm_crtc *crtc)
|
||||
{
|
||||
struct mga_device *mdev = crtc->dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(crtc->dev);
|
||||
u8 tmp;
|
||||
int iter_max;
|
||||
|
||||
|
@ -783,7 +784,7 @@ static void mga_g200wb_prepare(struct drm_crtc *crtc)
|
|||
static void mga_g200wb_commit(struct drm_crtc *crtc)
|
||||
{
|
||||
u8 tmp;
|
||||
struct mga_device *mdev = crtc->dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(crtc->dev);
|
||||
|
||||
/* 1- The first step is to ensure that the vrsten and hrsten are set */
|
||||
WREG8(MGAREG_CRTCEXT_INDEX, 1);
|
||||
|
@ -833,7 +834,7 @@ static void mga_g200wb_commit(struct drm_crtc *crtc)
|
|||
*/
|
||||
static void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
|
||||
{
|
||||
struct mga_device *mdev = crtc->dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(crtc->dev);
|
||||
u32 addr;
|
||||
int count;
|
||||
u8 crtcext0;
|
||||
|
@ -902,7 +903,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
|
|||
int x, int y, struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
const struct drm_framebuffer *fb = crtc->primary->fb;
|
||||
int hdisplay, hsyncstart, hsyncend, htotal;
|
||||
int vdisplay, vsyncstart, vsyncend, vtotal;
|
||||
|
@ -1135,9 +1136,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
|
|||
|
||||
WREG8(MGA_MISC_OUT, misc);
|
||||
|
||||
if (adjusted_mode)
|
||||
memcpy(&mdev->mode, mode, sizeof(struct drm_display_mode));
|
||||
|
||||
mga_crtc_do_set_base(crtc, old_fb, x, y, 0);
|
||||
|
||||
/* reset tagfifo */
|
||||
|
@ -1263,7 +1261,7 @@ static int mga_resume(struct drm_crtc *crtc)
|
|||
static void mga_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
u8 seq1 = 0, crtcext1 = 0;
|
||||
|
||||
switch (mode) {
|
||||
|
@ -1317,7 +1315,7 @@ static void mga_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
static void mga_crtc_prepare(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
u8 tmp;
|
||||
|
||||
/* mga_resume(crtc);*/
|
||||
|
@ -1353,7 +1351,7 @@ static void mga_crtc_prepare(struct drm_crtc *crtc)
|
|||
static void mga_crtc_commit(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
u8 tmp;
|
||||
|
||||
|
@ -1433,6 +1431,7 @@ static const struct drm_crtc_helper_funcs mga_helper_funcs = {
|
|||
/* CRTC setup */
|
||||
static void mga_crtc_init(struct mga_device *mdev)
|
||||
{
|
||||
struct drm_device *dev = mdev->dev;
|
||||
struct mga_crtc *mga_crtc;
|
||||
|
||||
mga_crtc = kzalloc(sizeof(struct mga_crtc) +
|
||||
|
@ -1442,14 +1441,17 @@ static void mga_crtc_init(struct mga_device *mdev)
|
|||
if (mga_crtc == NULL)
|
||||
return;
|
||||
|
||||
drm_crtc_init(mdev->dev, &mga_crtc->base, &mga_crtc_funcs);
|
||||
drm_crtc_init(dev, &mga_crtc->base, &mga_crtc_funcs);
|
||||
|
||||
drm_mode_crtc_set_gamma_size(&mga_crtc->base, MGAG200_LUT_SIZE);
|
||||
mdev->mode_info.crtc = mga_crtc;
|
||||
|
||||
drm_crtc_helper_add(&mga_crtc->base, &mga_helper_funcs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Connector
|
||||
*/
|
||||
|
||||
static int mga_vga_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct mga_connector *mga_connector = to_mga_connector(connector);
|
||||
|
@ -1495,7 +1497,7 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
|
|||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct mga_device *mdev = (struct mga_device*)dev->dev_private;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
int bpp = 32;
|
||||
|
||||
if (IS_G200_SE(mdev)) {
|
||||
|
@ -1574,7 +1576,6 @@ static void mga_connector_destroy(struct drm_connector *connector)
|
|||
struct mga_connector *mga_connector = to_mga_connector(connector);
|
||||
mgag200_i2c_destroy(mga_connector->i2c);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = {
|
||||
|
@ -1588,70 +1589,96 @@ static const struct drm_connector_funcs mga_vga_connector_funcs = {
|
|||
.destroy = mga_connector_destroy,
|
||||
};
|
||||
|
||||
static struct drm_connector *mga_vga_init(struct drm_device *dev)
|
||||
static int mgag200_vga_connector_init(struct mga_device *mdev)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct mga_connector *mga_connector;
|
||||
struct drm_device *dev = mdev->dev;
|
||||
struct mga_connector *mconnector = &mdev->connector;
|
||||
struct drm_connector *connector = &mconnector->base;
|
||||
struct mga_i2c_chan *i2c;
|
||||
int ret;
|
||||
|
||||
mga_connector = kzalloc(sizeof(struct mga_connector), GFP_KERNEL);
|
||||
if (!mga_connector)
|
||||
return NULL;
|
||||
|
||||
connector = &mga_connector->base;
|
||||
mga_connector->i2c = mgag200_i2c_create(dev);
|
||||
if (!mga_connector->i2c)
|
||||
DRM_ERROR("failed to add ddc bus\n");
|
||||
|
||||
drm_connector_init_with_ddc(dev, connector,
|
||||
&mga_vga_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_VGA,
|
||||
&mga_connector->i2c->adapter);
|
||||
i2c = mgag200_i2c_create(dev);
|
||||
if (!i2c)
|
||||
drm_warn(dev, "failed to add DDC bus\n");
|
||||
|
||||
ret = drm_connector_init_with_ddc(dev, connector,
|
||||
&mga_vga_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_VGA,
|
||||
&i2c->adapter);
|
||||
if (ret)
|
||||
goto err_mgag200_i2c_destroy;
|
||||
drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
|
||||
|
||||
drm_connector_register(connector);
|
||||
mconnector->i2c = i2c;
|
||||
|
||||
return connector;
|
||||
return 0;
|
||||
|
||||
err_mgag200_i2c_destroy:
|
||||
mgag200_i2c_destroy(i2c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct drm_mode_config_funcs mgag200_mode_config_funcs = {
|
||||
.fb_create = drm_gem_fb_create
|
||||
};
|
||||
|
||||
static unsigned int mgag200_preferred_depth(struct mga_device *mdev)
|
||||
{
|
||||
if (IS_G200_SE(mdev) && mdev->vram_fb_available < (2048*1024))
|
||||
return 16;
|
||||
else
|
||||
return 32;
|
||||
}
|
||||
|
||||
int mgag200_modeset_init(struct mga_device *mdev)
|
||||
{
|
||||
struct drm_device *dev = mdev->dev;
|
||||
struct drm_encoder *encoder = &mdev->encoder;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector *connector = &mdev->connector.base;
|
||||
int ret;
|
||||
|
||||
mdev->mode_info.mode_config_initialized = true;
|
||||
mdev->bpp_shifts[0] = 0;
|
||||
mdev->bpp_shifts[1] = 1;
|
||||
mdev->bpp_shifts[2] = 0;
|
||||
mdev->bpp_shifts[3] = 2;
|
||||
|
||||
mdev->dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH;
|
||||
mdev->dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT;
|
||||
ret = drmm_mode_config_init(dev);
|
||||
if (ret) {
|
||||
drm_err(dev, "drmm_mode_config_init() failed, error %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mdev->dev->mode_config.fb_base = mdev->mc.vram_base;
|
||||
dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH;
|
||||
dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT;
|
||||
|
||||
dev->mode_config.preferred_depth = mgag200_preferred_depth(mdev);
|
||||
dev->mode_config.prefer_shadow = 1;
|
||||
|
||||
dev->mode_config.fb_base = mdev->mc.vram_base;
|
||||
|
||||
dev->mode_config.funcs = &mgag200_mode_config_funcs;
|
||||
|
||||
mga_crtc_init(mdev);
|
||||
|
||||
ret = drm_simple_encoder_init(mdev->dev, encoder,
|
||||
DRM_MODE_ENCODER_DAC);
|
||||
ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC);
|
||||
if (ret) {
|
||||
drm_err(mdev->dev,
|
||||
drm_err(dev,
|
||||
"drm_simple_encoder_init() failed, error %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
encoder->possible_crtcs = 0x1;
|
||||
|
||||
connector = mga_vga_init(mdev->dev);
|
||||
if (!connector) {
|
||||
DRM_ERROR("mga_vga_init failed\n");
|
||||
return -1;
|
||||
ret = mgag200_vga_connector_init(mdev);
|
||||
if (ret) {
|
||||
drm_err(dev,
|
||||
"mgag200_vga_connector_init() failed, error %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_connector_attach_encoder(connector, encoder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mgag200_modeset_fini(struct mga_device *mdev)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,16 @@ config DRM_PANEL_ARM_VERSATILE
|
|||
reference designs. The panel is detected using special registers
|
||||
in the Versatile family syscon registers.
|
||||
|
||||
config DRM_PANEL_ASUS_Z00T_TM5P5_NT35596
|
||||
tristate "ASUS Z00T TM5P5 NT35596 panel"
|
||||
depends on GPIOLIB && OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable support for the ASUS TMP5P5
|
||||
NT35596 1080x1920 video mode panel as found in some Asus
|
||||
Zenfone 2 Laser Z00T devices.
|
||||
|
||||
config DRM_PANEL_BOE_HIMAX8279D
|
||||
tristate "Boe Himax8279d panel"
|
||||
depends on OF
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o
|
||||
obj-$(CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596) += panel-asus-z00t-tm5p5-n35596.o
|
||||
obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o
|
||||
obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o
|
||||
obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
|
||||
|
|
367
drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
Normal file
367
drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
Normal file
|
@ -0,0 +1,367 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct tm5p5_nt35596 {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator_bulk_data supplies[2];
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline struct tm5p5_nt35596 *to_tm5p5_nt35596(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct tm5p5_nt35596, panel);
|
||||
}
|
||||
|
||||
#define dsi_generic_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void tm5p5_nt35596_reset(struct tm5p5_nt35596 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
usleep_range(1000, 2000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(1000, 2000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
usleep_range(15000, 16000);
|
||||
}
|
||||
|
||||
static int tm5p5_nt35596_on(struct tm5p5_nt35596 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
|
||||
dsi_generic_write_seq(dsi, 0xff, 0x05);
|
||||
dsi_generic_write_seq(dsi, 0xfb, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xc5, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xff, 0x04);
|
||||
dsi_generic_write_seq(dsi, 0x01, 0x84);
|
||||
dsi_generic_write_seq(dsi, 0x05, 0x25);
|
||||
dsi_generic_write_seq(dsi, 0x06, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0x07, 0x20);
|
||||
dsi_generic_write_seq(dsi, 0x08, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0x09, 0x08);
|
||||
dsi_generic_write_seq(dsi, 0x0a, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0x0b, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0x0c, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0x0d, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x0e, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x0f, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x10, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x11, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x12, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x17, 0xf3);
|
||||
dsi_generic_write_seq(dsi, 0x18, 0xc0);
|
||||
dsi_generic_write_seq(dsi, 0x19, 0xc0);
|
||||
dsi_generic_write_seq(dsi, 0x1a, 0xc0);
|
||||
dsi_generic_write_seq(dsi, 0x1b, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0x1c, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0x1d, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0x1e, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0x1f, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0x20, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0xfb, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xff, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xfb, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0x35, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xd3, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xd4, 0x04);
|
||||
dsi_generic_write_seq(dsi, 0x5e, 0x0d);
|
||||
dsi_generic_write_seq(dsi, 0x11, 0x00);
|
||||
msleep(100);
|
||||
dsi_generic_write_seq(dsi, 0x29, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0x53, 0x24);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tm5p5_nt35596_off(struct tm5p5_nt35596 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(60);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0x4f, 0x01);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tm5p5_nt35596_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct tm5p5_nt35596 *ctx = to_tm5p5_nt35596(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tm5p5_nt35596_reset(ctx);
|
||||
|
||||
ret = tm5p5_nt35596_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),
|
||||
ctx->supplies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tm5p5_nt35596_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct tm5p5_nt35596 *ctx = to_tm5p5_nt35596(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = tm5p5_nt35596_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),
|
||||
ctx->supplies);
|
||||
|
||||
ctx->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode tm5p5_nt35596_mode = {
|
||||
.clock = (1080 + 100 + 8 + 16) * (1920 + 4 + 2 + 4) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 100,
|
||||
.hsync_end = 1080 + 100 + 8,
|
||||
.htotal = 1080 + 100 + 8 + 16,
|
||||
.vdisplay = 1920,
|
||||
.vsync_start = 1920 + 4,
|
||||
.vsync_end = 1920 + 4 + 2,
|
||||
.vtotal = 1920 + 4 + 2 + 4,
|
||||
.vrefresh = 60,
|
||||
.width_mm = 68,
|
||||
.height_mm = 121,
|
||||
};
|
||||
|
||||
static int tm5p5_nt35596_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &tm5p5_nt35596_mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs tm5p5_nt35596_panel_funcs = {
|
||||
.prepare = tm5p5_nt35596_prepare,
|
||||
.unprepare = tm5p5_nt35596_unprepare,
|
||||
.get_modes = tm5p5_nt35596_get_modes,
|
||||
};
|
||||
|
||||
static int tm5p5_nt35596_bl_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness = bl->props.brightness;
|
||||
int ret;
|
||||
|
||||
if (bl->props.power != FB_BLANK_UNBLANK ||
|
||||
bl->props.fb_blank != FB_BLANK_UNBLANK ||
|
||||
bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
|
||||
brightness = 0;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tm5p5_nt35596_bl_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness = bl->props.brightness;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return brightness & 0xff;
|
||||
}
|
||||
|
||||
static const struct backlight_ops tm5p5_nt35596_bl_ops = {
|
||||
.update_status = tm5p5_nt35596_bl_update_status,
|
||||
.get_brightness = tm5p5_nt35596_bl_get_brightness,
|
||||
};
|
||||
|
||||
static struct backlight_device *
|
||||
tm5p5_nt35596_create_backlight(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
const struct backlight_properties props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.brightness = 255,
|
||||
.max_brightness = 255,
|
||||
};
|
||||
|
||||
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
|
||||
&tm5p5_nt35596_bl_ops, &props);
|
||||
}
|
||||
|
||||
static int tm5p5_nt35596_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct tm5p5_nt35596 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->supplies[0].supply = "vdd";
|
||||
ctx->supplies[1].supply = "vddio";
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
|
||||
ctx->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to get regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset_gpio)) {
|
||||
ret = PTR_ERR(ctx->reset_gpio);
|
||||
dev_err(dev, "Failed to get reset-gpios: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_EOT_PACKET |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &tm5p5_nt35596_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ctx->panel.backlight = tm5p5_nt35596_create_backlight(dsi);
|
||||
if (IS_ERR(ctx->panel.backlight)) {
|
||||
ret = PTR_ERR(ctx->panel.backlight);
|
||||
dev_err(dev, "Failed to create backlight: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_panel_add(&ctx->panel);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add panel: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tm5p5_nt35596_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct tm5p5_nt35596 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev,
|
||||
"Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id tm5p5_nt35596_of_match[] = {
|
||||
{ .compatible = "asus,z00t-tm5p5-n35596" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tm5p5_nt35596_of_match);
|
||||
|
||||
static struct mipi_dsi_driver tm5p5_nt35596_driver = {
|
||||
.probe = tm5p5_nt35596_probe,
|
||||
.remove = tm5p5_nt35596_remove,
|
||||
.driver = {
|
||||
.name = "panel-tm5p5-nt35596",
|
||||
.of_match_table = tm5p5_nt35596_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(tm5p5_nt35596_driver);
|
||||
|
||||
MODULE_AUTHOR("Konrad Dybcio <konradybcio@gmail.com>");
|
||||
MODULE_DESCRIPTION("DRM driver for tm5p5 nt35596 1080p video mode dsi panel");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -108,6 +109,7 @@ struct panel_simple {
|
|||
struct i2c_adapter *ddc;
|
||||
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct gpio_desc *hpd_gpio;
|
||||
|
||||
struct drm_display_mode override_mode;
|
||||
};
|
||||
|
@ -259,11 +261,37 @@ static int panel_simple_unprepare(struct drm_panel *panel)
|
|||
return 0;
|
||||
}
|
||||
|
||||
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 we're called from probe we won't consider '-EPROBE_DEFER'
|
||||
* to be an error--we'll leave the error code in "hpd_gpio".
|
||||
* When we try to use it we'll 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) {
|
||||
dev_err(dev, "failed to get 'hpd' GPIO: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int panel_simple_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct panel_simple *p = to_panel_simple(panel);
|
||||
unsigned int delay;
|
||||
int err;
|
||||
int hpd_asserted;
|
||||
|
||||
if (p->prepared)
|
||||
return 0;
|
||||
|
@ -282,6 +310,26 @@ static int panel_simple_prepare(struct drm_panel *panel)
|
|||
if (delay)
|
||||
msleep(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) {
|
||||
dev_err(panel->dev,
|
||||
"error waiting for hpd GPIO: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
p->prepared = true;
|
||||
|
||||
return 0;
|
||||
|
@ -462,6 +510,11 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
|
|||
panel->desc = desc;
|
||||
|
||||
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)
|
||||
return err;
|
||||
}
|
||||
|
||||
panel->supply = devm_regulator_get(dev, "power");
|
||||
if (IS_ERR(panel->supply))
|
||||
|
@ -1173,6 +1226,7 @@ static const struct panel_desc boe_nv101wxmn51 = {
|
|||
},
|
||||
};
|
||||
|
||||
/* Also used for boe_nv133fhm_n62 */
|
||||
static const struct drm_display_mode boe_nv133fhm_n61_modes = {
|
||||
.clock = 147840,
|
||||
.hdisplay = 1920,
|
||||
|
@ -1186,13 +1240,14 @@ static const struct drm_display_mode boe_nv133fhm_n61_modes = {
|
|||
.vrefresh = 60,
|
||||
};
|
||||
|
||||
/* Also used for boe_nv133fhm_n62 */
|
||||
static const struct panel_desc boe_nv133fhm_n61 = {
|
||||
.modes = &boe_nv133fhm_n61_modes,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.bpc = 6,
|
||||
.size = {
|
||||
.width = 300,
|
||||
.height = 187,
|
||||
.width = 294,
|
||||
.height = 165,
|
||||
},
|
||||
.delay = {
|
||||
.hpd_absent_delay = 200,
|
||||
|
@ -3659,6 +3714,9 @@ static const struct of_device_id platform_of_match[] = {
|
|||
}, {
|
||||
.compatible = "boe,nv133fhm-n61",
|
||||
.data = &boe_nv133fhm_n61,
|
||||
}, {
|
||||
.compatible = "boe,nv133fhm-n62",
|
||||
.data = &boe_nv133fhm_n61,
|
||||
}, {
|
||||
.compatible = "boe,nv140fhmn49",
|
||||
.data = &boe_nv140fhmn49,
|
||||
|
|
|
@ -300,3 +300,4 @@ static struct mipi_dsi_driver visionox_rm69299_driver = {
|
|||
module_mipi_dsi_driver(visionox_rm69299_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Visionox RM69299 DSI Panel Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -557,12 +557,11 @@ static const struct fb_ops pxa168fb_ops = {
|
|||
.fb_imageblit = cfb_imageblit,
|
||||
};
|
||||
|
||||
static int pxa168fb_init_mode(struct fb_info *info,
|
||||
static void pxa168fb_init_mode(struct fb_info *info,
|
||||
struct pxa168fb_mach_info *mi)
|
||||
{
|
||||
struct pxa168fb_info *fbi = info->par;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
int ret = 0;
|
||||
u32 total_w, total_h, refresh;
|
||||
u64 div_result;
|
||||
const struct fb_videomode *m;
|
||||
|
@ -593,8 +592,6 @@ static int pxa168fb_init_mode(struct fb_info *info,
|
|||
div_result = 1000000000000ll;
|
||||
do_div(div_result, total_w * total_h * refresh);
|
||||
var->pixclock = (u32)div_result;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pxa168fb_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -354,9 +354,12 @@ extern "C" {
|
|||
* a platform-dependent stride. On top of that the memory can apply
|
||||
* platform-depending swizzling of some higher address bits into bit6.
|
||||
*
|
||||
* This format is highly platforms specific and not useful for cross-driver
|
||||
* sharing. It exists since on a given platform it does uniquely identify the
|
||||
* layout in a simple way for i915-specific userspace.
|
||||
* Note that this layout is only accurate on intel gen 8+ or valleyview chipsets.
|
||||
* On earlier platforms the is highly platforms specific and not useful for
|
||||
* cross-driver sharing. It exists since on a given platform it does uniquely
|
||||
* identify the layout in a simple way for i915-specific userspace, which
|
||||
* facilitated conversion of userspace to modifiers. Additionally the exact
|
||||
* format on some really old platforms is not known.
|
||||
*/
|
||||
#define I915_FORMAT_MOD_X_TILED fourcc_mod_code(INTEL, 1)
|
||||
|
||||
|
@ -369,9 +372,12 @@ extern "C" {
|
|||
* memory can apply platform-depending swizzling of some higher address bits
|
||||
* into bit6.
|
||||
*
|
||||
* This format is highly platforms specific and not useful for cross-driver
|
||||
* sharing. It exists since on a given platform it does uniquely identify the
|
||||
* layout in a simple way for i915-specific userspace.
|
||||
* Note that this layout is only accurate on intel gen 8+ or valleyview chipsets.
|
||||
* On earlier platforms the is highly platforms specific and not useful for
|
||||
* cross-driver sharing. It exists since on a given platform it does uniquely
|
||||
* identify the layout in a simple way for i915-specific userspace, which
|
||||
* facilitated conversion of userspace to modifiers. Additionally the exact
|
||||
* format on some really old platforms is not known.
|
||||
*/
|
||||
#define I915_FORMAT_MOD_Y_TILED fourcc_mod_code(INTEL, 2)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user