mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
DRM: add drm support for g12a
PD#160546: DRM: add drm support for g12a Verified on g12a Change-Id: I5bfa4ad388e181af629e013a8d7c516ae5fc3fa4 Signed-off-by: Yalong Liu <yalong.liu@amlogic.com>
This commit is contained in:
@@ -14133,6 +14133,9 @@ AMLOGIC DRM DRIVER
|
||||
M: Sky Zhou <sky.zhou@amlogic.com>
|
||||
F: driver/amlogic/drm/*
|
||||
F: driver/amlogic/drm/am_meson_fbdev.c
|
||||
F: include/linux/amlogic/meson_drm.h
|
||||
F: arch/arm64/boot/dts/amlogic/g12a_skt_buildroot.dts
|
||||
F: arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi
|
||||
|
||||
AMLOGIC ADD S400EMMC DTS
|
||||
M: Yue Gui <yuegui.he@amlogic.com>
|
||||
|
||||
1687
arch/arm64/boot/dts/amlogic/g12a_skt_buildroot.dts
Normal file
1687
arch/arm64/boot/dts/amlogic/g12a_skt_buildroot.dts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
||||
|
||||
/ {
|
||||
|
||||
dvalin@0xffe40000 {
|
||||
gpu:dvalin@0xffe40000 {
|
||||
compatible = "arm,malit60x", "arm,malit6xx", "arm,mali-midgard";
|
||||
#cooling-cells = <2>; /* min followed by max */
|
||||
reg = <0 0xFFE40000 0 0x04000>, /*mali APB bus base address*/
|
||||
|
||||
66
arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi
Normal file
66
arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* arch/arm64/boot/dts/amlogic/meson_drm.dtsi
|
||||
*
|
||||
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/ {
|
||||
venc-cvbs {
|
||||
status = "okay";
|
||||
compatible = "amlogic,meson-gxbb-cvbs";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
enc_cvbs_in: port@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
|
||||
venc_cvbs_in_vpu: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&vpu_out_venc_cvbs>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
drm_vpu:drm@d0100000 {
|
||||
status = "okay";
|
||||
compatible = "amlogic,meson-gxbb";
|
||||
reg = <0x0 0xd0100000 0x0 0x100000>,
|
||||
<0x0 0xc883c000 0x0 0x1000>,
|
||||
<0x0 0xc8838000 0x0 0x1000>;
|
||||
reg-names = "base", "hhi", "dmc";
|
||||
interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
|
||||
dma-coherent;
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
vpu_out: port@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
|
||||
vpu_out_venc_cvbs: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&venc_cvbs_in_vpu>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -139,8 +139,6 @@ static bool am_meson_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
|
||||
void am_meson_crtc_enable(struct drm_crtc *crtc)
|
||||
{
|
||||
enum vmode_e mode;
|
||||
int ret = 0;
|
||||
char *name;
|
||||
struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
|
||||
|
||||
@@ -152,19 +150,7 @@ void am_meson_crtc_enable(struct drm_crtc *crtc)
|
||||
//DRM_INFO("meson_crtc_enable %s\n", adjusted_mode->name);
|
||||
name = am_meson_crtc_get_voutmode(adjusted_mode);
|
||||
|
||||
mode = validate_vmode(name);
|
||||
if (mode == VMODE_MAX) {
|
||||
DRM_ERROR("no matched vout mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &mode);
|
||||
ret = set_current_vmode(mode);
|
||||
if (ret)
|
||||
DRM_ERROR("new mode %s set error\n", name);
|
||||
else
|
||||
DRM_INFO("new mode %s set ok\n", name);
|
||||
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode);
|
||||
set_vout_mode(name);
|
||||
}
|
||||
|
||||
void am_meson_crtc_disable(struct drm_crtc *crtc)
|
||||
|
||||
@@ -43,20 +43,25 @@ static int am_meson_gem_alloc_ion_buff(
|
||||
if (!meson_gem_obj)
|
||||
return -EINVAL;
|
||||
|
||||
//TODO,check flags to set different ion heap type.
|
||||
handle = ion_alloc(client, meson_gem_obj->base.size,
|
||||
//check flags to set different ion heap type.
|
||||
//if flags is set to 0, need to use ion dma buffer.
|
||||
if (((flags & (BO_USE_SCANOUT | BO_USE_CURSOR)) != 0)
|
||||
|| (flags == 0)) {
|
||||
handle = ion_alloc(client, meson_gem_obj->base.size,
|
||||
0, (1 << ION_HEAP_TYPE_DMA), 0);
|
||||
if (IS_ERR(handle)) {
|
||||
}
|
||||
else {
|
||||
handle = ion_alloc(client, meson_gem_obj->base.size,
|
||||
0, (1 << ION_HEAP_TYPE_SYSTEM), 0);
|
||||
if (IS_ERR(handle)) {
|
||||
DRM_ERROR("am_meson_gem_alloc_ion_buff FAILED.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bscatter = true;
|
||||
}
|
||||
|
||||
if (IS_ERR(handle)) {
|
||||
DRM_ERROR("%s: FAILED, flags:0x%x.\n",
|
||||
__func__, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
meson_gem_obj->handle = handle;
|
||||
meson_gem_obj->bscatter = bscatter;
|
||||
DRM_DEBUG("%s: allocate handle (%p).\n",
|
||||
@@ -313,6 +318,42 @@ unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int am_meson_gem_create_ioctl(
|
||||
struct drm_device *dev,
|
||||
void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct am_meson_gem_object *meson_gem_obj;
|
||||
struct meson_drm *drmdrv = dev->dev_private;
|
||||
struct ion_client *client = (struct ion_client *)drmdrv->gem_client;
|
||||
struct drm_meson_gem_create *args = data;
|
||||
int ret = 0;
|
||||
|
||||
meson_gem_obj = am_meson_gem_object_create(
|
||||
dev, args->flags, args->size, client);
|
||||
if (IS_ERR(meson_gem_obj))
|
||||
return PTR_ERR(meson_gem_obj);
|
||||
|
||||
/*
|
||||
* allocate a id of idr table where the obj is registered
|
||||
* and handle has the id what user can see.
|
||||
*/
|
||||
ret = drm_gem_handle_create(file_priv,
|
||||
&meson_gem_obj->base, &args->handle);
|
||||
/* drop reference from allocate - handle holds it now. */
|
||||
drm_gem_object_unreference_unlocked(&meson_gem_obj->base);
|
||||
if (ret) {
|
||||
DRM_ERROR("%s: create dumb handle failed %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DRM_DEBUG("%s: create dumb %p with gem handle (0x%x)\n",
|
||||
__func__, meson_gem_obj, args->handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int am_meson_gem_create(struct meson_drm *drmdrv)
|
||||
{
|
||||
drmdrv->gem_client = meson_ion_client_create(-1, "meson-gem");
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
|
||||
#ifndef __AM_MESON_GEM_H
|
||||
#define __AM_MESON_GEM_H
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <linux/amlogic/meson_drm.h>
|
||||
#include <ion/ion_priv.h>
|
||||
#include "meson_drv.h"
|
||||
|
||||
@@ -50,6 +51,11 @@ int am_meson_gem_dumb_destroy(
|
||||
struct drm_device *dev,
|
||||
uint32_t handle);
|
||||
|
||||
int am_meson_gem_create_ioctl(
|
||||
struct drm_device *dev,
|
||||
void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
int am_meson_gem_dumb_map_offset(
|
||||
struct drm_file *file_priv,
|
||||
struct drm_device *dev,
|
||||
|
||||
@@ -140,7 +140,7 @@ void am_osd_do_display(
|
||||
meson_fb = container_of(fb, struct am_meson_fb, base);
|
||||
phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
|
||||
if (meson_fb->bufp->bscatter)
|
||||
DRM_ERROR("ERROR:am_meson_plane meet a scatter framebuffe.\nr");
|
||||
DRM_ERROR("ERROR:am_meson_plane meet a scatter framebuffer.\n");
|
||||
#else
|
||||
/* Update Canvas with buffer address */
|
||||
gem = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
|
||||
@@ -90,20 +90,6 @@ static struct osd_device_data_s osd_gxbb = {
|
||||
.dummy_data = 0x00808000,
|
||||
};
|
||||
|
||||
static struct osd_device_data_s osd_gxtvbb = {
|
||||
.cpu_id = __MESON_CPU_MAJOR_ID_GXTVBB,
|
||||
.osd_ver = OSD_NORMAL,
|
||||
.afbc_type = MESON_AFBC,
|
||||
.osd_count = 2,
|
||||
.has_deband = 0,
|
||||
.has_lut = 0,
|
||||
.has_rdma = 1,
|
||||
.has_dolby_vision = 0,
|
||||
.osd_fifo_len = 32,
|
||||
.vpp_fifo_len = 0xfff,
|
||||
.dummy_data = 0x0,
|
||||
};
|
||||
|
||||
static struct osd_device_data_s osd_gxl = {
|
||||
.cpu_id = __MESON_CPU_MAJOR_ID_GXL,
|
||||
.osd_ver = OSD_NORMAL,
|
||||
@@ -286,6 +272,13 @@ static irqreturn_t meson_irq(int irq, void *arg)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_MESON_USE_ION
|
||||
static const struct drm_ioctl_desc meson_ioctls[] = {
|
||||
DRM_IOCTL_DEF_DRV(MESON_GEM_CREATE, am_meson_gem_create_ioctl,
|
||||
DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct file_operations fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
@@ -340,6 +333,8 @@ static struct drm_driver meson_driver = {
|
||||
.dumb_map_offset = am_meson_gem_dumb_map_offset,
|
||||
.gem_free_object_unlocked = am_meson_gem_object_free,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.ioctls = meson_ioctls,
|
||||
.num_ioctls = ARRAY_SIZE(meson_ioctls),
|
||||
#else
|
||||
/* PRIME Ops */
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
@@ -614,10 +609,6 @@ static int meson_drv_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto free_drm;
|
||||
|
||||
#ifdef CONFIG_DRM_MESON_BYPASS_MODE
|
||||
osd_drm_debugfs_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
free_drm:
|
||||
|
||||
@@ -693,6 +693,8 @@ void osd_drm_debugfs_add(
|
||||
struct dentry *ent;
|
||||
int i;
|
||||
|
||||
osd_drm_debugfs_init();
|
||||
|
||||
plane_osd_id[osd_id] = osd_id;
|
||||
*plane_debugfs_dir = debugfs_create_dir(name, osd_debugfs_root);
|
||||
if (!plane_debugfs_dir)
|
||||
@@ -712,6 +714,8 @@ EXPORT_SYMBOL(osd_drm_debugfs_add);
|
||||
|
||||
void osd_drm_debugfs_init(void)
|
||||
{
|
||||
if (osd_debugfs_root)
|
||||
return;
|
||||
osd_debugfs_root = debugfs_create_dir("graphics", NULL);
|
||||
if (!osd_debugfs_root)
|
||||
pr_err("can't create debugfs dir\n");
|
||||
|
||||
@@ -33,6 +33,11 @@ struct osd_plane_map_s {
|
||||
u32 dst_w;
|
||||
u32 dst_h;
|
||||
int byte_stride;
|
||||
u32 background_w;
|
||||
u32 background_h;
|
||||
u32 premult_en;
|
||||
u32 afbc_en;
|
||||
u32 afbc_inter_format;
|
||||
u32 reserve;
|
||||
};
|
||||
|
||||
|
||||
@@ -6257,6 +6257,35 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map)
|
||||
plane_map->byte_stride,
|
||||
plane_map->src_h,
|
||||
CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
|
||||
if (osd_hw.hwc_enable) {
|
||||
#if 1
|
||||
plane_map->zorder = 1;
|
||||
plane_map->premult_en = 0;
|
||||
plane_map->background_w = 1920;
|
||||
plane_map->background_h = 1080;
|
||||
plane_map->afbc_inter_format = 0x3;
|
||||
plane_map->afbc_en = 0;
|
||||
#endif
|
||||
/* just get para, need update via do_hwc */
|
||||
osd_hw.order[index] = plane_map->zorder;
|
||||
osd_hw.premult_en[index] = plane_map->premult_en;
|
||||
osd_hw.background_w = plane_map->background_w;
|
||||
osd_hw.background_h = plane_map->background_h;
|
||||
osd_hw.osd_afbcd[index].enable = plane_map->afbc_en;
|
||||
osd_hw.osd_afbcd[index].inter_format =
|
||||
plane_map->afbc_inter_format;
|
||||
|
||||
osd_hw.src_data[index].x = plane_map->src_x;
|
||||
osd_hw.src_data[index].y = plane_map->src_y;
|
||||
osd_hw.src_data[index].w = plane_map->src_w;
|
||||
osd_hw.src_data[index].h = plane_map->src_h;
|
||||
|
||||
osd_hw.dst_data[index].x = plane_map->dst_x;
|
||||
osd_hw.dst_data[index].y = plane_map->dst_y;
|
||||
osd_hw.dst_data[index].w = plane_map->dst_w;
|
||||
osd_hw.dst_data[index].h = plane_map->dst_h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
width_dst = osd_hw.free_dst_data_backup[index].x_end -
|
||||
osd_hw.free_dst_data_backup[index].x_start + 1;
|
||||
@@ -6668,9 +6697,11 @@ void osd_page_flip(struct osd_plane_map_s *plane_map)
|
||||
} else {
|
||||
if (plane_map->phy_addr && plane_map->src_w
|
||||
&& plane_map->src_h) {
|
||||
#if 1
|
||||
osd_hw.fb_gem[index].canvas_idx =
|
||||
osd_extra_idx[index][ext_canvas_id];
|
||||
ext_canvas_id ^= 1;
|
||||
#endif
|
||||
color = convert_panel_format(plane_map->format);
|
||||
if (color) {
|
||||
osd_hw.color_info[index] = color;
|
||||
|
||||
@@ -186,7 +186,7 @@ char *get_vout_mode_uboot(void)
|
||||
}
|
||||
EXPORT_SYMBOL(get_vout_mode_uboot);
|
||||
|
||||
static int set_vout_mode(char *name)
|
||||
int set_vout_mode(char *name)
|
||||
{
|
||||
enum vmode_e mode;
|
||||
int ret = 0;
|
||||
|
||||
@@ -119,4 +119,6 @@ extern void vdac_enable(bool on, unsigned int module_sel);
|
||||
extern char *get_vout_mode_internal(void);
|
||||
extern char *get_vout_mode_uboot(void);
|
||||
|
||||
extern int set_vout_mode(char *name);
|
||||
|
||||
#endif /* _VOUT_NOTIFY_H_ */
|
||||
|
||||
72
include/linux/amlogic/meson_drm.h
Normal file
72
include/linux/amlogic/meson_drm.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* include/uapi/drm/meson_drm.h
|
||||
*
|
||||
* Copyright (C) 2016 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _MESON_DRM_H
|
||||
#define _MESON_DRM_H
|
||||
|
||||
#include <drm/drm.h>
|
||||
|
||||
/* memory type definitions. */
|
||||
enum drm_meson_gem_mem_type {
|
||||
/* Physically Continuous memory. */
|
||||
MESON_BO_CONTIG = 1 << 0,
|
||||
/* cachable mapping. */
|
||||
MESON_BO_CACHABLE = 1 << 1,
|
||||
/* write-combine mapping. */
|
||||
MESON_BO_WC = 1 << 2,
|
||||
MESON_BO_SECURE = 1 << 3,
|
||||
MESON_BO_MASK = MESON_BO_CONTIG | MESON_BO_CACHABLE |
|
||||
MESON_BO_WC
|
||||
};
|
||||
|
||||
/* Use flags */
|
||||
#define BO_USE_NONE 0
|
||||
#define BO_USE_SCANOUT (1ull << 0)
|
||||
#define BO_USE_CURSOR (1ull << 1)
|
||||
#define BO_USE_CURSOR_64X64 BO_USE_CURSOR
|
||||
#define BO_USE_RENDERING (1ull << 2)
|
||||
#define BO_USE_LINEAR (1ull << 3)
|
||||
#define BO_USE_SW_READ_NEVER (1ull << 4)
|
||||
#define BO_USE_SW_READ_RARELY (1ull << 5)
|
||||
#define BO_USE_SW_READ_OFTEN (1ull << 6)
|
||||
#define BO_USE_SW_WRITE_NEVER (1ull << 7)
|
||||
#define BO_USE_SW_WRITE_RARELY (1ull << 8)
|
||||
#define BO_USE_SW_WRITE_OFTEN (1ull << 9)
|
||||
#define BO_USE_EXTERNAL_DISP (1ull << 10)
|
||||
#define BO_USE_PROTECTED (1ull << 11)
|
||||
#define BO_USE_HW_VIDEO_ENCODER (1ull << 12)
|
||||
#define BO_USE_CAMERA_WRITE (1ull << 13)
|
||||
#define BO_USE_CAMERA_READ (1ull << 14)
|
||||
#define BO_USE_RENDERSCRIPT (1ull << 16)
|
||||
#define BO_USE_TEXTURE (1ull << 17)
|
||||
|
||||
|
||||
/**
|
||||
* User-desired buffer creation information structure.
|
||||
*
|
||||
* @size: user-desired memory allocation size.
|
||||
* @flags: user request for setting memory type or cache attributes.
|
||||
* @handle: returned a handle to created gem object.
|
||||
* - this handle will be set by gem module of kernel side.
|
||||
*/
|
||||
struct drm_meson_gem_create {
|
||||
uint64_t size;
|
||||
uint32_t flags;
|
||||
uint32_t handle;
|
||||
};
|
||||
|
||||
#define DRM_MESON_GEM_CREATE 0x00
|
||||
|
||||
#define DRM_IOCTL_MESON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \
|
||||
DRM_MESON_GEM_CREATE, struct drm_meson_gem_create)
|
||||
|
||||
#endif /* _MESON_DRM_H */
|
||||
|
||||
Reference in New Issue
Block a user