+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_buf.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#include <drm/drmP.h>
-#include <drm/rockchip_drm.h>
-
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_gem.h"
-#include "rockchip_drm_buf.h"
-#include "rockchip_drm_iommu.h"
-
-static int lowlevel_buffer_allocate(struct drm_device *dev,
- unsigned int flags, struct rockchip_drm_gem_buf *buf)
-{
- int ret = 0;
- enum dma_attr attr;
- unsigned int nr_pages;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (buf->dma_addr) {
- DRM_DEBUG_KMS("already allocated.\n");
- return 0;
- }
-
- init_dma_attrs(&buf->dma_attrs);
-
- /*
- * if ROCKCHIP_BO_CONTIG, fully physically contiguous memory
- * region will be allocated else physically contiguous
- * as possible.
- */
- if (!(flags & ROCKCHIP_BO_NONCONTIG))
- dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &buf->dma_attrs);
-
- /*
- * if ROCKCHIP_BO_WC or ROCKCHIP_BO_NONCACHABLE, writecombine mapping
- * else cachable mapping.
- */
- if (flags & ROCKCHIP_BO_WC || !(flags & ROCKCHIP_BO_CACHABLE))
- attr = DMA_ATTR_WRITE_COMBINE;
- else
- attr = DMA_ATTR_NON_CONSISTENT;
-
- dma_set_attr(attr, &buf->dma_attrs);
- dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
-
- nr_pages = buf->size >> PAGE_SHIFT;
-
- if (!is_drm_iommu_supported(dev)) {
- dma_addr_t start_addr;
- unsigned int i = 0;
-
- buf->pages = kzalloc(sizeof(struct page) * nr_pages,
- GFP_KERNEL);
- if (!buf->pages) {
- DRM_ERROR("failed to allocate pages.\n");
- return -ENOMEM;
- }
-
- buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size,
- &buf->dma_addr, GFP_KERNEL,
- &buf->dma_attrs);
- if (!buf->kvaddr) {
- DRM_ERROR("failed to allocate buffer.\n");
- kfree(buf->pages);
- return -ENOMEM;
- }
-
- start_addr = buf->dma_addr;
- while (i < nr_pages) {
- buf->pages[i] = phys_to_page(start_addr);
- start_addr += PAGE_SIZE;
- i++;
- }
- } else {
-
- buf->pages = dma_alloc_attrs(dev->dev, buf->size,
- &buf->dma_addr, GFP_KERNEL,
- &buf->dma_attrs);
- if (!buf->pages) {
- DRM_ERROR("failed to allocate buffer.\n");
- return -ENOMEM;
- }
- }
-
- buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages);
- if (!buf->sgt) {
- DRM_ERROR("failed to get sg table.\n");
- ret = -ENOMEM;
- goto err_free_attrs;
- }
-
- DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
- (unsigned long)buf->dma_addr,
- buf->size);
-
- return ret;
-
-err_free_attrs:
- dma_free_attrs(dev->dev, buf->size, buf->pages,
- (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
- buf->dma_addr = (dma_addr_t)NULL;
-
- if (!is_drm_iommu_supported(dev))
- kfree(buf->pages);
-
- return ret;
-}
-
-static void lowlevel_buffer_deallocate(struct drm_device *dev,
- unsigned int flags, struct rockchip_drm_gem_buf *buf)
-{
- DRM_DEBUG_KMS("%s.\n", __FILE__);
-
- if (!buf->dma_addr) {
- DRM_DEBUG_KMS("dma_addr is invalid.\n");
- return;
- }
-
- DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
- (unsigned long)buf->dma_addr,
- buf->size);
-
- sg_free_table(buf->sgt);
-
- kfree(buf->sgt);
- buf->sgt = NULL;
-
- if (!is_drm_iommu_supported(dev)) {
- dma_free_attrs(dev->dev, buf->size, buf->kvaddr,
- (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
- kfree(buf->pages);
- } else
- dma_free_attrs(dev->dev, buf->size, buf->pages,
- (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
-
- buf->dma_addr = (dma_addr_t)NULL;
-}
-
-struct rockchip_drm_gem_buf *rockchip_drm_init_buf(struct drm_device *dev,
- unsigned int size)
-{
- struct rockchip_drm_gem_buf *buffer;
-
- DRM_DEBUG_KMS("%s.\n", __FILE__);
- DRM_DEBUG_KMS("desired size = 0x%x\n", size);
-
- buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
- if (!buffer) {
- DRM_ERROR("failed to allocate rockchip_drm_gem_buf.\n");
- return NULL;
- }
-
- buffer->size = size;
- return buffer;
-}
-
-void rockchip_drm_fini_buf(struct drm_device *dev,
- struct rockchip_drm_gem_buf *buffer)
-{
- DRM_DEBUG_KMS("%s.\n", __FILE__);
-
- if (!buffer) {
- DRM_DEBUG_KMS("buffer is null.\n");
- return;
- }
-
- kfree(buffer);
- buffer = NULL;
-}
-
-int rockchip_drm_alloc_buf(struct drm_device *dev,
- struct rockchip_drm_gem_buf *buf, unsigned int flags)
-{
-
- /*
- * allocate memory region and set the memory information
- * to vaddr and dma_addr of a buffer object.
- */
- if (lowlevel_buffer_allocate(dev, flags, buf) < 0)
- return -ENOMEM;
-
- return 0;
-}
-
-void rockchip_drm_free_buf(struct drm_device *dev,
- unsigned int flags, struct rockchip_drm_gem_buf *buffer)
-{
-
- lowlevel_buffer_deallocate(dev, flags, buffer);
-}
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_buf.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#ifndef _ROCKCHIP_DRM_BUF_H_
-#define _ROCKCHIP_DRM_BUF_H_
-
-/* create and initialize buffer object. */
-struct rockchip_drm_gem_buf *rockchip_drm_init_buf(struct drm_device *dev,
- unsigned int size);
-
-/* destroy buffer object. */
-void rockchip_drm_fini_buf(struct drm_device *dev,
- struct rockchip_drm_gem_buf *buffer);
-
-/* allocate physical memory region and setup sgt. */
-int rockchip_drm_alloc_buf(struct drm_device *dev,
- struct rockchip_drm_gem_buf *buf,
- unsigned int flags);
-
-/* release physical memory region, and sgt. */
-void rockchip_drm_free_buf(struct drm_device *dev,
- unsigned int flags,
- struct rockchip_drm_gem_buf *buffer);
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_connector.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-
-#include <drm/rockchip_drm.h>
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_encoder.h"
-
-#define to_rockchip_connector(x) container_of(x, struct rockchip_drm_connector,\
- drm_connector)
-
-struct rockchip_drm_connector {
- struct drm_connector drm_connector;
- uint32_t encoder_id;
- struct rockchip_drm_manager *manager;
- uint32_t dpms;
-};
-
-/* convert rockchip_video_timings to drm_display_mode */
-static inline void
-convert_to_display_mode(struct drm_display_mode *mode,
- struct rockchip_drm_panel_info *panel)
-{
- struct fb_videomode *timing = &panel->timing;
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- mode->clock = timing->pixclock / 1000;
- mode->vrefresh = timing->refresh;
-
- mode->hdisplay = timing->xres;
- mode->hsync_start = mode->hdisplay + timing->right_margin;
- mode->hsync_end = mode->hsync_start + timing->hsync_len;
- mode->htotal = mode->hsync_end + timing->left_margin;
-
- mode->vdisplay = timing->yres;
- mode->vsync_start = mode->vdisplay + timing->lower_margin;
- mode->vsync_end = mode->vsync_start + timing->vsync_len;
- mode->vtotal = mode->vsync_end + timing->upper_margin;
- mode->width_mm = panel->width_mm;
- mode->height_mm = panel->height_mm;
-
- if (timing->vmode & FB_VMODE_INTERLACED)
- mode->flags |= DRM_MODE_FLAG_INTERLACE;
-
- if (timing->vmode & FB_VMODE_DOUBLE)
- mode->flags |= DRM_MODE_FLAG_DBLSCAN;
-}
-static inline void
-convert_fbmode_to_display_mode(struct drm_display_mode *mode,
- struct fb_videomode *timing)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- mode->clock = timing->pixclock / 1000;
- mode->vrefresh = timing->refresh;
-
- mode->hdisplay = timing->xres;
- mode->hsync_start = mode->hdisplay + timing->right_margin;
- mode->hsync_end = mode->hsync_start + timing->hsync_len;
- mode->htotal = mode->hsync_end + timing->left_margin;
-
- mode->vdisplay = timing->yres;
- mode->vsync_start = mode->vdisplay + timing->lower_margin;
- mode->vsync_end = mode->vsync_start + timing->vsync_len;
- mode->vtotal = mode->vsync_end + timing->upper_margin;
-
- if (timing->vmode & FB_VMODE_INTERLACED)
- mode->flags |= DRM_MODE_FLAG_INTERLACE;
-
- if (timing->vmode & FB_VMODE_DOUBLE)
- mode->flags |= DRM_MODE_FLAG_DBLSCAN;
-}
-/* convert drm_display_mode to rockchip_video_timings */
-static inline void
-convert_to_video_timing(struct fb_videomode *timing,
- struct drm_display_mode *mode)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- memset(timing, 0, sizeof(*timing));
-
- timing->pixclock = mode->clock * 1000;
- timing->refresh = drm_mode_vrefresh(mode);
-
- timing->xres = mode->hdisplay;
- timing->right_margin = mode->hsync_start - mode->hdisplay;
- timing->hsync_len = mode->hsync_end - mode->hsync_start;
- timing->left_margin = mode->htotal - mode->hsync_end;
-
- timing->yres = mode->vdisplay;
- timing->lower_margin = mode->vsync_start - mode->vdisplay;
- timing->vsync_len = mode->vsync_end - mode->vsync_start;
- timing->upper_margin = mode->vtotal - mode->vsync_end;
-
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- timing->vmode = FB_VMODE_INTERLACED;
- else
- timing->vmode = FB_VMODE_NONINTERLACED;
-
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- timing->vmode |= FB_VMODE_DOUBLE;
-}
-
-static int rockchip_drm_connector_get_modes(struct drm_connector *connector)
-{
- struct rockchip_drm_connector *rockchip_connector =
- to_rockchip_connector(connector);
- struct rockchip_drm_manager *manager = rockchip_connector->manager;
- struct rockchip_drm_display_ops *display_ops = manager->display_ops;
- struct edid *edid = NULL;
- unsigned int count = 0;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!display_ops) {
- DRM_DEBUG_KMS("display_ops is null.\n");
- return 0;
- }
-
- /*
- * if get_edid() exists then get_edid() callback of hdmi side
- * is called to get edid data through i2c interface else
- * get timing from the FIMD driver(display controller).
- *
- * P.S. in case of lcd panel, count is always 1 if success
- * because lcd panel has only one mode.
- */
- if (display_ops->get_edid) {
- edid = display_ops->get_edid(manager->dev, connector);
- if (IS_ERR_OR_NULL(edid)) {
- ret = PTR_ERR(edid);
- edid = NULL;
- DRM_ERROR("Panel operation get_edid failed %d\n", ret);
- goto out;
- }
-
- count = drm_add_edid_modes(connector, edid);
- if (!count) {
- DRM_ERROR("Add edid modes failed %d\n", count);
- goto out;
- }
-
- drm_mode_connector_update_edid_property(connector, edid);
- } else if(display_ops->get_modelist){
- struct list_head *pos,*head;
- struct fb_modelist *modelist;
- struct fb_videomode *mode;
- struct drm_display_mode *disp_mode = NULL;
- count=0;
- head = display_ops->get_modelist(manager->dev);
-
- list_for_each(pos,head){
- modelist = list_entry(pos, struct fb_modelist, list);
- mode = &modelist->mode;
- disp_mode = drm_mode_create(connector->dev);
- if (!mode) {
- DRM_ERROR("failed to create a new display mode.\n");
- return count;
- }
- convert_fbmode_to_display_mode(disp_mode, mode);
-
- if(mode->xres == 1280 && mode->yres == 720 && mode->refresh == 60)
- disp_mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- drm_mode_set_name(disp_mode);
-// snprintf(disp_mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s-%d",
-// disp_mode->hdisplay, disp_mode->vdisplay,
-// !!(disp_mode->flags & DRM_MODE_FLAG_INTERLACE)? "i" : "p",disp_mode->vrefresh);
- drm_mode_probed_add(connector, disp_mode);
- count++;
- }
- } else {
- struct rockchip_drm_panel_info *panel;
- struct drm_display_mode *mode = drm_mode_create(connector->dev);
- if (!mode) {
- DRM_ERROR("failed to create a new display mode.\n");
- return 0;
- }
-
- if (display_ops->get_panel)
- panel = display_ops->get_panel(manager->dev);
- else {
- drm_mode_destroy(connector->dev, mode);
- return 0;
- }
-
- convert_to_display_mode(mode, panel);
- connector->display_info.width_mm = mode->width_mm;
- connector->display_info.height_mm = mode->height_mm;
-
- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
- drm_mode_set_name(mode);
- drm_mode_probed_add(connector, mode);
-
- count = 1;
- }
-
-out:
- kfree(edid);
- return count;
-}
-
-static int rockchip_drm_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct rockchip_drm_connector *rockchip_connector =
- to_rockchip_connector(connector);
- struct rockchip_drm_manager *manager = rockchip_connector->manager;
- struct rockchip_drm_display_ops *display_ops = manager->display_ops;
- struct fb_videomode timing;
- int ret = MODE_BAD;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- convert_to_video_timing(&timing, mode);
-
- if (display_ops && display_ops->check_timing)
- if (!display_ops->check_timing(manager->dev, (void *)&timing))
- ret = MODE_OK;
-
- return ret;
-}
-
-struct drm_encoder *rockchip_drm_best_encoder(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct rockchip_drm_connector *rockchip_connector =
- to_rockchip_connector(connector);
- struct drm_mode_object *obj;
- struct drm_encoder *encoder;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- obj = drm_mode_object_find(dev, rockchip_connector->encoder_id,
- DRM_MODE_OBJECT_ENCODER);
- if (!obj) {
- DRM_DEBUG_KMS("Unknown ENCODER ID %d\n",
- rockchip_connector->encoder_id);
- return NULL;
- }
-
- encoder = obj_to_encoder(obj);
-
- return encoder;
-}
-
-static struct drm_connector_helper_funcs rockchip_connector_helper_funcs = {
- .get_modes = rockchip_drm_connector_get_modes,
- .mode_valid = rockchip_drm_connector_mode_valid,
- .best_encoder = rockchip_drm_best_encoder,
-};
-
-void rockchip_drm_display_power(struct drm_connector *connector, int mode)
-{
- struct drm_encoder *encoder = rockchip_drm_best_encoder(connector);
- struct rockchip_drm_connector *rockchip_connector;
- struct rockchip_drm_manager *manager = rockchip_drm_get_manager(encoder);
- struct rockchip_drm_display_ops *display_ops = manager->display_ops;
-
- rockchip_connector = to_rockchip_connector(connector);
-
- if (rockchip_connector->dpms == mode) {
- DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
- return;
- }
-
- if (display_ops && display_ops->power_on)
- display_ops->power_on(manager->dev, mode);
-
- rockchip_connector->dpms = mode;
-}
-
-static void rockchip_drm_connector_dpms(struct drm_connector *connector,
- int mode)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * in case that drm_crtc_helper_set_mode() is called,
- * encoder/crtc->funcs->dpms() will be just returned
- * because they already were DRM_MODE_DPMS_ON so only
- * rockchip_drm_display_power() will be called.
- */
- drm_helper_connector_dpms(connector, mode);
-
- rockchip_drm_display_power(connector, mode);
-
-}
-
-static int rockchip_drm_connector_fill_modes(struct drm_connector *connector,
- unsigned int max_width, unsigned int max_height)
-{
- struct rockchip_drm_connector *rockchip_connector =
- to_rockchip_connector(connector);
- struct rockchip_drm_manager *manager = rockchip_connector->manager;
- struct rockchip_drm_manager_ops *ops = manager->ops;
- unsigned int width, height;
-
- width = max_width;
- height = max_height;
-
- /*
- * if specific driver want to find desired_mode using maxmum
- * resolution then get max width and height from that driver.
- */
- if (ops && ops->get_max_resol)
- ops->get_max_resol(manager->dev, &width, &height);
-
- return drm_helper_probe_single_connector_modes(connector, width,
- height);
-}
-
-/* get detection status of display device. */
-static enum drm_connector_status
-rockchip_drm_connector_detect(struct drm_connector *connector, bool force)
-{
- struct rockchip_drm_connector *rockchip_connector =
- to_rockchip_connector(connector);
- struct rockchip_drm_manager *manager = rockchip_connector->manager;
- struct rockchip_drm_display_ops *display_ops =
- manager->display_ops;
- enum drm_connector_status status = connector_status_disconnected;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (display_ops && display_ops->is_connected) {
- if (display_ops->is_connected(manager->dev))
- status = connector_status_connected;
- else
- status = connector_status_disconnected;
- }
-
- return status;
-}
-
-static void rockchip_drm_connector_destroy(struct drm_connector *connector)
-{
- struct rockchip_drm_connector *rockchip_connector =
- to_rockchip_connector(connector);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
- kfree(rockchip_connector);
-}
-
-static struct drm_connector_funcs rockchip_connector_funcs = {
- .dpms = rockchip_drm_connector_dpms,
- .fill_modes = rockchip_drm_connector_fill_modes,
- .detect = rockchip_drm_connector_detect,
- .destroy = rockchip_drm_connector_destroy,
-};
-
-struct drm_connector *rockchip_drm_connector_create(struct drm_device *dev,
- struct drm_encoder *encoder)
-{
- struct rockchip_drm_connector *rockchip_connector;
- struct rockchip_drm_manager *manager = rockchip_drm_get_manager(encoder);
- struct drm_connector *connector;
- int type;
- int err;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- rockchip_connector = kzalloc(sizeof(*rockchip_connector), GFP_KERNEL);
- if (!rockchip_connector) {
- DRM_ERROR("failed to allocate connector\n");
- return NULL;
- }
-
- connector = &rockchip_connector->drm_connector;
-
- switch (manager->display_ops->type) {
- case ROCKCHIP_DISPLAY_TYPE_HDMI:
- type = DRM_MODE_CONNECTOR_HDMIA;
- connector->interlace_allowed = true;
- connector->polled = DRM_CONNECTOR_POLL_HPD;
- break;
- case ROCKCHIP_DISPLAY_TYPE_VIDI:
- type = DRM_MODE_CONNECTOR_VIRTUAL;
- connector->polled = DRM_CONNECTOR_POLL_HPD;
- break;
- case ROCKCHIP_DISPLAY_TYPE_LCD:
- type = DRM_MODE_CONNECTOR_LVDS;
- break;
- default:
- type = DRM_MODE_CONNECTOR_Unknown;
- break;
- }
-
- drm_connector_init(dev, connector, &rockchip_connector_funcs, type);
- drm_connector_helper_add(connector, &rockchip_connector_helper_funcs);
-
- err = drm_sysfs_connector_add(connector);
- if (err)
- goto err_connector;
-
- rockchip_connector->encoder_id = encoder->base.id;
- rockchip_connector->manager = manager;
- rockchip_connector->dpms = DRM_MODE_DPMS_OFF;
- connector->dpms = DRM_MODE_DPMS_OFF;
- connector->encoder = encoder;
-
- err = drm_mode_connector_attach_encoder(connector, encoder);
- if (err) {
- DRM_ERROR("failed to attach a connector to a encoder\n");
- goto err_sysfs;
- }
-
- DRM_DEBUG_KMS("connector has been created\n");
-
- return connector;
-
-err_sysfs:
- drm_sysfs_connector_remove(connector);
-err_connector:
- drm_connector_cleanup(connector);
- kfree(rockchip_connector);
- return NULL;
-}
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_connector.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#ifndef _ROCKCHIP_DRM_CONNECTOR_H_
-#define _ROCKCHIP_DRM_CONNECTOR_H_
-
-struct drm_connector *rockchip_drm_connector_create(struct drm_device *dev,
- struct drm_encoder *encoder);
-
-struct drm_encoder *rockchip_drm_best_encoder(struct drm_connector *connector);
-
-void rockchip_drm_display_power(struct drm_connector *connector, int mode);
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_core.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#include <drm/drmP.h>
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_encoder.h"
-#include "rockchip_drm_connector.h"
-#include "rockchip_drm_fbdev.h"
-
-static LIST_HEAD(rockchip_drm_subdrv_list);
-
-static int rockchip_drm_create_enc_conn(struct drm_device *dev,
- struct rockchip_drm_subdrv *subdrv)
-{
- struct drm_encoder *encoder;
- struct drm_connector *connector;
- int ret;
-
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- subdrv->manager->dev = subdrv->dev;
-
- /* create and initialize a encoder for this sub driver. */
- encoder = rockchip_drm_encoder_create(dev, subdrv->manager,
- (1 << MAX_CRTC) - 1);
- if (!encoder) {
- DRM_ERROR("failed to create encoder\n");
- return -EFAULT;
- }
-
- /*
- * create and initialize a connector for this sub driver and
- * attach the encoder created above to the connector.
- */
- connector = rockchip_drm_connector_create(dev, encoder);
- if (!connector) {
- DRM_ERROR("failed to create connector\n");
- ret = -EFAULT;
- goto err_destroy_encoder;
- }
-
- subdrv->encoder = encoder;
- subdrv->connector = connector;
-
- return 0;
-
-err_destroy_encoder:
- encoder->funcs->destroy(encoder);
- return ret;
-}
-
-static void rockchip_drm_destroy_enc_conn(struct rockchip_drm_subdrv *subdrv)
-{
- if (subdrv->encoder) {
- struct drm_encoder *encoder = subdrv->encoder;
- encoder->funcs->destroy(encoder);
- subdrv->encoder = NULL;
- }
-
- if (subdrv->connector) {
- struct drm_connector *connector = subdrv->connector;
- connector->funcs->destroy(connector);
- subdrv->connector = NULL;
- }
-}
-
-static int rockchip_drm_subdrv_probe(struct drm_device *dev,
- struct rockchip_drm_subdrv *subdrv)
-{
- if (subdrv->probe) {
- int ret;
-
- subdrv->drm_dev = dev;
-
- /*
- * this probe callback would be called by sub driver
- * after setting of all resources to this sub driver,
- * such as clock, irq and register map are done or by load()
- * of rockchip drm driver.
- *
- * P.S. note that this driver is considered for modularization.
- */
- ret = subdrv->probe(dev, subdrv->dev);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static void rockchip_drm_subdrv_remove(struct drm_device *dev,
- struct rockchip_drm_subdrv *subdrv)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (subdrv->remove)
- subdrv->remove(dev, subdrv->dev);
-}
-
-int rockchip_drm_device_register(struct drm_device *dev)
-{
- struct rockchip_drm_subdrv *subdrv, *n;
- unsigned int fine_cnt = 0;
- int err;
-
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (!dev)
- return -EINVAL;
-
- list_for_each_entry_safe(subdrv, n, &rockchip_drm_subdrv_list, list) {
- err = rockchip_drm_subdrv_probe(dev, subdrv);
- if (err) {
- DRM_DEBUG("rockchip drm subdrv probe failed.\n");
- list_del(&subdrv->list);
- continue;
- }
-
- /*
- * if manager is null then it means that this sub driver
- * doesn't need encoder and connector.
- */
- if (!subdrv->manager) {
- fine_cnt++;
- continue;
- }
-
- err = rockchip_drm_create_enc_conn(dev, subdrv);
- if (err) {
- DRM_DEBUG("failed to create encoder and connector.\n");
- rockchip_drm_subdrv_remove(dev, subdrv);
- list_del(&subdrv->list);
- continue;
- }
-
- fine_cnt++;
- }
-
- if (!fine_cnt)
- return -EINVAL;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rockchip_drm_device_register);
-
-int rockchip_drm_device_unregister(struct drm_device *dev)
-{
- struct rockchip_drm_subdrv *subdrv;
-
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (!dev) {
- WARN(1, "Unexpected drm device unregister!\n");
- return -EINVAL;
- }
-
- list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
- rockchip_drm_subdrv_remove(dev, subdrv);
- rockchip_drm_destroy_enc_conn(subdrv);
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rockchip_drm_device_unregister);
-
-int rockchip_drm_subdrv_register(struct rockchip_drm_subdrv *subdrv)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (!subdrv)
- return -EINVAL;
-
- list_add_tail(&subdrv->list, &rockchip_drm_subdrv_list);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rockchip_drm_subdrv_register);
-
-int rockchip_drm_subdrv_unregister(struct rockchip_drm_subdrv *subdrv)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (!subdrv)
- return -EINVAL;
-
- list_del(&subdrv->list);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rockchip_drm_subdrv_unregister);
-
-int rockchip_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
-{
- struct rockchip_drm_subdrv *subdrv;
- int ret;
-
- list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
- if (subdrv->open) {
- ret = subdrv->open(dev, subdrv->dev, file);
- if (ret)
- goto err;
- }
- }
-
- return 0;
-
-err:
- list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
- if (subdrv->close)
- subdrv->close(dev, subdrv->dev, file);
- }
- return ret;
-}
-EXPORT_SYMBOL_GPL(rockchip_drm_subdrv_open);
-
-void rockchip_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
-{
- struct rockchip_drm_subdrv *subdrv;
-
- list_for_each_entry(subdrv, &rockchip_drm_subdrv_list, list) {
- if (subdrv->close)
- subdrv->close(dev, subdrv->dev, file);
- }
-}
-EXPORT_SYMBOL_GPL(rockchip_drm_subdrv_close);
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_crtc.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_encoder.h"
-#include "rockchip_drm_plane.h"
-
-#define to_rockchip_crtc(x) container_of(x, struct rockchip_drm_crtc,\
- drm_crtc)
-
-enum rockchip_crtc_mode {
- CRTC_MODE_NORMAL, /* normal mode */
- CRTC_MODE_BLANK, /* The private plane of crtc is blank */
-};
-
-/*
- * Exynos specific crtc structure.
- *
- * @drm_crtc: crtc object.
- * @drm_plane: pointer of private plane object for this crtc
- * @pipe: a crtc index created at load() with a new crtc object creation
- * and the crtc object would be set to private->crtc array
- * to get a crtc object corresponding to this pipe from private->crtc
- * array when irq interrupt occured. the reason of using this pipe is that
- * drm framework doesn't support multiple irq yet.
- * we can refer to the crtc to current hardware interrupt occured through
- * this pipe value.
- * @dpms: store the crtc dpms value
- * @mode: store the crtc mode value
- */
-struct rockchip_drm_crtc {
- struct drm_crtc drm_crtc;
- struct drm_plane *plane;
- unsigned int pipe;
- unsigned int dpms;
- enum rockchip_crtc_mode mode;
- wait_queue_head_t pending_flip_queue;
- atomic_t pending_flip;
-};
-
-static void rockchip_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(crtc);
-
-// printk(KERN_ERR"crtc[%d] mode[%d]\n", crtc->base.id, mode);
-
- if (rockchip_crtc->dpms == mode) {
- DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
- return;
- }
-
- if (mode > DRM_MODE_DPMS_ON) {
- /* wait for the completion of page flip. */
- wait_event(rockchip_crtc->pending_flip_queue,
- atomic_read(&rockchip_crtc->pending_flip) == 0);
- drm_vblank_off(crtc->dev, rockchip_crtc->pipe);
- }
-
- rockchip_drm_fn_encoder(crtc, &mode, rockchip_drm_encoder_crtc_dpms);
- rockchip_crtc->dpms = mode;
-}
-
-static void rockchip_drm_crtc_prepare(struct drm_crtc *crtc)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* drm framework doesn't check NULL. */
-}
-
-static void rockchip_drm_crtc_commit(struct drm_crtc *crtc)
-{
- struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(crtc);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- rockchip_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
- rockchip_plane_commit(rockchip_crtc->plane);
- rockchip_plane_dpms(rockchip_crtc->plane, DRM_MODE_DPMS_ON);
-}
-
-static bool
-rockchip_drm_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* drm framework doesn't check NULL */
- return true;
-}
-
-static int
-rockchip_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode, int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(crtc);
- struct drm_plane *plane = rockchip_crtc->plane;
- unsigned int crtc_w;
- unsigned int crtc_h;
- int pipe = rockchip_crtc->pipe;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * copy the mode data adjusted by mode_fixup() into crtc->mode
- * so that hardware can be seet to proper mode.
- */
- memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
-
- crtc_w = crtc->fb->width - x;
- crtc_h = crtc->fb->height - y;
-
- ret = rockchip_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h,
- x, y, crtc_w, crtc_h);
- if (ret)
- return ret;
-
- plane->crtc = crtc;
- plane->fb = crtc->fb;
-
- rockchip_drm_fn_encoder(crtc, &pipe, rockchip_drm_encoder_crtc_pipe);
-
- return 0;
-}
-
-static int rockchip_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(crtc);
- struct drm_plane *plane = rockchip_crtc->plane;
- unsigned int crtc_w;
- unsigned int crtc_h;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* when framebuffer changing is requested, crtc's dpms should be on */
- if (rockchip_crtc->dpms > DRM_MODE_DPMS_ON) {
- DRM_ERROR("failed framebuffer changing request.\n");
-// return -EPERM;
- }
-
- crtc_w = crtc->fb->width - x;
- crtc_h = crtc->fb->height - y;
-
- ret = rockchip_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h,
- x, y, crtc_w, crtc_h);
- if (ret)
- return ret;
-
- rockchip_drm_crtc_commit(crtc);
-
- return 0;
-}
-
-static void rockchip_drm_crtc_load_lut(struct drm_crtc *crtc)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
- /* drm framework doesn't check NULL */
-}
-
-static void rockchip_drm_crtc_disable(struct drm_crtc *crtc)
-{
- struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(crtc);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- rockchip_plane_dpms(rockchip_crtc->plane, DRM_MODE_DPMS_OFF);
- rockchip_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static struct drm_crtc_helper_funcs rockchip_crtc_helper_funcs = {
- .dpms = rockchip_drm_crtc_dpms,
- .prepare = rockchip_drm_crtc_prepare,
- .commit = rockchip_drm_crtc_commit,
- .mode_fixup = rockchip_drm_crtc_mode_fixup,
- .mode_set = rockchip_drm_crtc_mode_set,
- .mode_set_base = rockchip_drm_crtc_mode_set_base,
- .load_lut = rockchip_drm_crtc_load_lut,
- .disable = rockchip_drm_crtc_disable,
-};
-
-static int rockchip_drm_crtc_page_flip(struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event)
-{
- struct drm_device *dev = crtc->dev;
- struct rockchip_drm_private *dev_priv = dev->dev_private;
- struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(crtc);
- struct drm_framebuffer *old_fb = crtc->fb;
- int ret = -EINVAL;
-
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* when the page flip is requested, crtc's dpms should be on */
- if (rockchip_crtc->dpms > DRM_MODE_DPMS_ON) {
- DRM_ERROR("failed page flip request.\n");
- return -EINVAL;
- }
-
- mutex_lock(&dev->struct_mutex);
-
- if (event) {
- /*
- * the pipe from user always is 0 so we can set pipe number
- * of current owner to event.
- */
- event->pipe = rockchip_crtc->pipe;
-
- ret = drm_vblank_get(dev, rockchip_crtc->pipe);
- if (ret) {
- DRM_DEBUG("failed to acquire vblank counter\n");
-
- goto out;
- }
-
- spin_lock_irq(&dev->event_lock);
- list_add_tail(&event->base.link,
- &dev_priv->pageflip_event_list);
- atomic_set(&rockchip_crtc->pending_flip, 1);
- spin_unlock_irq(&dev->event_lock);
-
- crtc->fb = fb;
- ret = rockchip_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y,
- NULL);
- if (ret) {
- crtc->fb = old_fb;
-
- spin_lock_irq(&dev->event_lock);
- drm_vblank_put(dev, rockchip_crtc->pipe);
- list_del(&event->base.link);
- spin_unlock_irq(&dev->event_lock);
-
- goto out;
- }
- }
-out:
- mutex_unlock(&dev->struct_mutex);
- return ret;
-}
-
-static void rockchip_drm_crtc_destroy(struct drm_crtc *crtc)
-{
- struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(crtc);
- struct rockchip_drm_private *private = crtc->dev->dev_private;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- private->crtc[rockchip_crtc->pipe] = NULL;
-
- drm_crtc_cleanup(crtc);
- kfree(rockchip_crtc);
-}
-
-static int rockchip_drm_crtc_set_property(struct drm_crtc *crtc,
- struct drm_property *property,
- uint64_t val)
-{
- struct drm_device *dev = crtc->dev;
- struct rockchip_drm_private *dev_priv = dev->dev_private;
- struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(crtc);
-
- DRM_DEBUG_KMS("%s\n", __func__);
-
- if (property == dev_priv->crtc_mode_property) {
- enum rockchip_crtc_mode mode = val;
-
- if (mode == rockchip_crtc->mode)
- return 0;
-
- rockchip_crtc->mode = mode;
-
- switch (mode) {
- case CRTC_MODE_NORMAL:
- rockchip_drm_crtc_commit(crtc);
- break;
- case CRTC_MODE_BLANK:
- rockchip_plane_dpms(rockchip_crtc->plane,
- DRM_MODE_DPMS_OFF);
- break;
- default:
- break;
- }
-
- return 0;
- }
-
- return -EINVAL;
-}
-
-static struct drm_crtc_funcs rockchip_crtc_funcs = {
- .set_config = drm_crtc_helper_set_config,
- .page_flip = rockchip_drm_crtc_page_flip,
- .destroy = rockchip_drm_crtc_destroy,
- .set_property = rockchip_drm_crtc_set_property,
-};
-
-static const struct drm_prop_enum_list mode_names[] = {
- { CRTC_MODE_NORMAL, "normal" },
- { CRTC_MODE_BLANK, "blank" },
-};
-
-static void rockchip_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct rockchip_drm_private *dev_priv = dev->dev_private;
- struct drm_property *prop;
-
- DRM_DEBUG_KMS("%s\n", __func__);
-
- prop = dev_priv->crtc_mode_property;
- if (!prop) {
- prop = drm_property_create_enum(dev, 0, "mode", mode_names,
- ARRAY_SIZE(mode_names));
- if (!prop)
- return;
-
- dev_priv->crtc_mode_property = prop;
- }
-
- drm_object_attach_property(&crtc->base, prop, 0);
-}
-
-int rockchip_drm_crtc_create(struct drm_device *dev, unsigned int nr)
-{
- struct rockchip_drm_crtc *rockchip_crtc;
- struct rockchip_drm_private *private = dev->dev_private;
- struct drm_crtc *crtc;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- rockchip_crtc = kzalloc(sizeof(*rockchip_crtc), GFP_KERNEL);
- if (!rockchip_crtc) {
- DRM_ERROR("failed to allocate rockchip crtc\n");
- return -ENOMEM;
- }
-
- rockchip_crtc->pipe = nr;
- rockchip_crtc->dpms = DRM_MODE_DPMS_OFF;
- init_waitqueue_head(&rockchip_crtc->pending_flip_queue);
- atomic_set(&rockchip_crtc->pending_flip, 0);
- rockchip_crtc->plane = rockchip_plane_init(dev, 1 << nr, true);
- if (!rockchip_crtc->plane) {
- kfree(rockchip_crtc);
- return -ENOMEM;
- }
-
- crtc = &rockchip_crtc->drm_crtc;
-
- private->crtc[nr] = crtc;
-
- drm_crtc_init(dev, crtc, &rockchip_crtc_funcs);
- drm_crtc_helper_add(crtc, &rockchip_crtc_helper_funcs);
-
- rockchip_drm_crtc_attach_mode_property(crtc);
-
- return 0;
-}
-#if 0
-int rockchip_get_crtc_vblank_timestamp(struct drm_device *dev, int crtc,
- int *max_error,
- struct timeval *vblank_time,
- unsigned flags)
-{
- struct rockchip_drm_private *private = dev->dev_private;
- struct rockchip_drm_crtc *rockchip_crtc =
- to_rockchip_crtc(private->crtc[crtc]);
-
- if (rockchip_crtc->dpms != DRM_MODE_DPMS_ON)
- return -EPERM;
-
- rockchip_drm_fn_encoder(private->crtc[crtc], &crtc,
- rockchip_get_vblank_timestamp);
-
-}
-#endif
-int rockchip_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
-{
- struct rockchip_drm_private *private = dev->dev_private;
- struct rockchip_drm_crtc *rockchip_crtc =
- to_rockchip_crtc(private->crtc[crtc]);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (rockchip_crtc->dpms != DRM_MODE_DPMS_ON)
- return -EPERM;
-
- rockchip_drm_fn_encoder(private->crtc[crtc], &crtc,
- rockchip_drm_enable_vblank);
-
- return 0;
-}
-
-void rockchip_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
-{
- struct rockchip_drm_private *private = dev->dev_private;
- struct rockchip_drm_crtc *rockchip_crtc =
- to_rockchip_crtc(private->crtc[crtc]);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (rockchip_crtc->dpms != DRM_MODE_DPMS_ON)
- return;
-
- rockchip_drm_fn_encoder(private->crtc[crtc], &crtc,
- rockchip_drm_disable_vblank);
-}
-
-void rockchip_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
-{
- struct rockchip_drm_private *dev_priv = dev->dev_private;
- struct drm_pending_vblank_event *e, *t;
- struct drm_crtc *drm_crtc = dev_priv->crtc[crtc];
- struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(drm_crtc);
- unsigned long flags;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- spin_lock_irqsave(&dev->event_lock, flags);
-
- list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
- base.link) {
- /* if event's pipe isn't same as crtc then ignore it. */
- if (crtc != e->pipe)
- continue;
-
- list_del(&e->base.link);
- drm_send_vblank_event(dev, -1, e);
- drm_vblank_put(dev, crtc);
- atomic_set(&rockchip_crtc->pending_flip, 0);
- wake_up(&rockchip_crtc->pending_flip_queue);
- }
-
- spin_unlock_irqrestore(&dev->event_lock, flags);
-}
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#ifndef _ROCKCHIP_DRM_CRTC_H_
-#define _ROCKCHIP_DRM_CRTC_H_
-
-int rockchip_drm_crtc_create(struct drm_device *dev, unsigned int nr);
-int rockchip_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
-void rockchip_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
-void rockchip_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc);
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_dmabuf.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#include <drm/drmP.h>
-#include <drm/rockchip_drm.h>
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_gem.h"
-
-#include <linux/dma-buf.h>
-
-struct rockchip_drm_dmabuf_attachment {
- struct sg_table sgt;
- enum dma_data_direction dir;
- bool is_mapped;
-};
-
-static int rockchip_gem_attach_dma_buf(struct dma_buf *dmabuf,
- struct device *dev,
- struct dma_buf_attachment *attach)
-{
- struct rockchip_drm_dmabuf_attachment *rockchip_attach;
-
- rockchip_attach = kzalloc(sizeof(*rockchip_attach), GFP_KERNEL);
- if (!rockchip_attach)
- return -ENOMEM;
-
- rockchip_attach->dir = DMA_NONE;
- attach->priv = rockchip_attach;
-
- return 0;
-}
-
-static void rockchip_gem_detach_dma_buf(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attach)
-{
- struct rockchip_drm_dmabuf_attachment *rockchip_attach = attach->priv;
- struct sg_table *sgt;
-
- if (!rockchip_attach)
- return;
-
- sgt = &rockchip_attach->sgt;
-
- if (rockchip_attach->dir != DMA_NONE)
- dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents,
- rockchip_attach->dir);
-
- sg_free_table(sgt);
- kfree(rockchip_attach);
- attach->priv = NULL;
-}
-
-static struct sg_table *
- rockchip_gem_map_dma_buf(struct dma_buf_attachment *attach,
- enum dma_data_direction dir)
-{
- struct rockchip_drm_dmabuf_attachment *rockchip_attach = attach->priv;
- struct rockchip_drm_gem_obj *gem_obj = attach->dmabuf->priv;
- struct drm_device *dev = gem_obj->base.dev;
- struct rockchip_drm_gem_buf *buf;
- struct scatterlist *rd, *wr;
- struct sg_table *sgt = NULL;
- unsigned int i;
- int nents, ret;
-
- DRM_DEBUG_PRIME("%s\n", __FILE__);
-
- /* just return current sgt if already requested. */
- if (rockchip_attach->dir == dir && rockchip_attach->is_mapped)
- return &rockchip_attach->sgt;
-
- buf = gem_obj->buffer;
- if (!buf) {
- DRM_ERROR("buffer is null.\n");
- return ERR_PTR(-ENOMEM);
- }
-
- sgt = &rockchip_attach->sgt;
-
- ret = sg_alloc_table(sgt, buf->sgt->orig_nents, GFP_KERNEL);
- if (ret) {
- DRM_ERROR("failed to alloc sgt.\n");
- return ERR_PTR(-ENOMEM);
- }
-
- mutex_lock(&dev->struct_mutex);
-
- rd = buf->sgt->sgl;
- wr = sgt->sgl;
- for (i = 0; i < sgt->orig_nents; ++i) {
- sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
- rd = sg_next(rd);
- wr = sg_next(wr);
- }
-
- if (dir != DMA_NONE) {
- nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
- if (!nents) {
- DRM_ERROR("failed to map sgl with iommu.\n");
- sg_free_table(sgt);
- sgt = ERR_PTR(-EIO);
- goto err_unlock;
- }
- }
-
- rockchip_attach->is_mapped = true;
- rockchip_attach->dir = dir;
- attach->priv = rockchip_attach;
-
- DRM_DEBUG_PRIME("buffer size = 0x%lx\n", buf->size);
-
-err_unlock:
- mutex_unlock(&dev->struct_mutex);
- return sgt;
-}
-
-static void rockchip_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
- struct sg_table *sgt,
- enum dma_data_direction dir)
-{
- /* Nothing to do. */
-}
-
-static void rockchip_dmabuf_release(struct dma_buf *dmabuf)
-{
- struct rockchip_drm_gem_obj *rockchip_gem_obj = dmabuf->priv;
-
- DRM_DEBUG_PRIME("%s\n", __FILE__);
-
- /*
- * rockchip_dmabuf_release() call means that file object's
- * f_count is 0 and it calls drm_gem_object_handle_unreference()
- * to drop the references that these values had been increased
- * at drm_prime_handle_to_fd()
- */
- if (rockchip_gem_obj->base.export_dma_buf == dmabuf) {
- rockchip_gem_obj->base.export_dma_buf = NULL;
-
- /*
- * drop this gem object refcount to release allocated buffer
- * and resources.
- */
- drm_gem_object_unreference_unlocked(&rockchip_gem_obj->base);
- }
-}
-
-static void *rockchip_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
- unsigned long page_num)
-{
- /* TODO */
-
- return NULL;
-}
-
-static void rockchip_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
- unsigned long page_num,
- void *addr)
-{
- /* TODO */
-}
-
-static void *rockchip_gem_dmabuf_kmap(struct dma_buf *dma_buf,
- unsigned long page_num)
-{
- /* TODO */
-
- return NULL;
-}
-
-static void rockchip_gem_dmabuf_kunmap(struct dma_buf *dma_buf,
- unsigned long page_num, void *addr)
-{
- /* TODO */
-}
-
-static int rockchip_gem_dmabuf_mmap(struct dma_buf *dma_buf,
- struct vm_area_struct *vma)
-{
- return -ENOTTY;
-}
-
-static struct dma_buf_ops rockchip_dmabuf_ops = {
- .attach = rockchip_gem_attach_dma_buf,
- .detach = rockchip_gem_detach_dma_buf,
- .map_dma_buf = rockchip_gem_map_dma_buf,
- .unmap_dma_buf = rockchip_gem_unmap_dma_buf,
- .kmap = rockchip_gem_dmabuf_kmap,
- .kmap_atomic = rockchip_gem_dmabuf_kmap_atomic,
- .kunmap = rockchip_gem_dmabuf_kunmap,
- .kunmap_atomic = rockchip_gem_dmabuf_kunmap_atomic,
- .mmap = rockchip_gem_dmabuf_mmap,
- .release = rockchip_dmabuf_release,
-};
-
-struct dma_buf *rockchip_dmabuf_prime_export(struct drm_device *drm_dev,
- struct drm_gem_object *obj, int flags)
-{
- struct rockchip_drm_gem_obj *rockchip_gem_obj = to_rockchip_gem_obj(obj);
-
- return dma_buf_export(rockchip_gem_obj, &rockchip_dmabuf_ops,
- rockchip_gem_obj->base.size, flags);
-}
-
-struct drm_gem_object *rockchip_dmabuf_prime_import(struct drm_device *drm_dev,
- struct dma_buf *dma_buf)
-{
- struct dma_buf_attachment *attach;
- struct sg_table *sgt;
- struct scatterlist *sgl;
- struct rockchip_drm_gem_obj *rockchip_gem_obj;
- struct rockchip_drm_gem_buf *buffer;
- int ret;
-
- DRM_DEBUG_PRIME("%s\n", __FILE__);
-
- /* is this one of own objects? */
- if (dma_buf->ops == &rockchip_dmabuf_ops) {
- struct drm_gem_object *obj;
-
- rockchip_gem_obj = dma_buf->priv;
- obj = &rockchip_gem_obj->base;
-
- /* is it from our device? */
- if (obj->dev == drm_dev) {
- /*
- * Importing dmabuf exported from out own gem increases
- * refcount on gem itself instead of f_count of dmabuf.
- */
- drm_gem_object_reference(obj);
- return obj;
- }
- }
-
- attach = dma_buf_attach(dma_buf, drm_dev->dev);
- if (IS_ERR(attach))
- return ERR_PTR(-EINVAL);
-
- get_dma_buf(dma_buf);
-
- sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
- if (IS_ERR_OR_NULL(sgt)) {
- ret = PTR_ERR(sgt);
- goto err_buf_detach;
- }
-
- buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
- if (!buffer) {
- DRM_ERROR("failed to allocate rockchip_drm_gem_buf.\n");
- ret = -ENOMEM;
- goto err_unmap_attach;
- }
-
- rockchip_gem_obj = rockchip_drm_gem_init(drm_dev, dma_buf->size);
- if (!rockchip_gem_obj) {
- ret = -ENOMEM;
- goto err_free_buffer;
- }
-
- sgl = sgt->sgl;
-
- buffer->size = dma_buf->size;
- buffer->dma_addr = sg_dma_address(sgl);
-
- if (sgt->nents == 1) {
- /* always physically continuous memory if sgt->nents is 1. */
- rockchip_gem_obj->flags |= ROCKCHIP_BO_CONTIG;
- } else {
- /*
- * this case could be CONTIG or NONCONTIG type but for now
- * sets NONCONTIG.
- * TODO. we have to find a way that exporter can notify
- * the type of its own buffer to importer.
- */
- rockchip_gem_obj->flags |= ROCKCHIP_BO_NONCONTIG;
- }
-
- rockchip_gem_obj->buffer = buffer;
- buffer->sgt = sgt;
- rockchip_gem_obj->base.import_attach = attach;
-
- DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n", buffer->dma_addr,
- buffer->size);
-
- return &rockchip_gem_obj->base;
-
-err_free_buffer:
- kfree(buffer);
- buffer = NULL;
-err_unmap_attach:
- dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
-err_buf_detach:
- dma_buf_detach(dma_buf, attach);
- dma_buf_put(dma_buf);
-
- return ERR_PTR(ret);
-}
-
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_dmabuf.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#ifndef _ROCKCHIP_DRM_DMABUF_H_
-#define _ROCKCHIP_DRM_DMABUF_H_
-
-#ifdef CONFIG_DRM_ROCKCHIP_DMABUF
-struct dma_buf *rockchip_dmabuf_prime_export(struct drm_device *drm_dev,
- struct drm_gem_object *obj, int flags);
-
-struct drm_gem_object *rockchip_dmabuf_prime_import(struct drm_device *drm_dev,
- struct dma_buf *dma_buf);
-#else
-#define rockchip_dmabuf_prime_export NULL
-#define rockchip_dmabuf_prime_import NULL
-#endif
-#endif
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_encoder.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_encoder.h"
-#include "rockchip_drm_connector.h"
-
-#define to_rockchip_encoder(x) container_of(x, struct rockchip_drm_encoder,\
- drm_encoder)
-
-/*
- * rockchip specific encoder structure.
- *
- * @drm_encoder: encoder object.
- * @manager: specific encoder has its own manager to control a hardware
- * appropriately and we can access a hardware drawing on this manager.
- * @dpms: store the encoder dpms value.
- * @updated: indicate whether overlay data updating is needed or not.
- */
-struct rockchip_drm_encoder {
- struct drm_crtc *old_crtc;
- struct drm_encoder drm_encoder;
- struct rockchip_drm_manager *manager;
- int dpms;
- bool updated;
-};
-
-static void rockchip_drm_connector_power(struct drm_encoder *encoder, int mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_connector *connector;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (rockchip_drm_best_encoder(connector) == encoder) {
- DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
- connector->base.id, mode);
-
- rockchip_drm_display_power(connector, mode);
- }
- }
-}
-
-static void rockchip_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
- struct drm_device *dev = encoder->dev;
- struct rockchip_drm_manager *manager = rockchip_drm_get_manager(encoder);
- struct rockchip_drm_manager_ops *manager_ops = manager->ops;
- struct rockchip_drm_encoder *rockchip_encoder = to_rockchip_encoder(encoder);
-
- DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
-
- if (rockchip_encoder->dpms == mode) {
- DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
- return;
- }
-
- mutex_lock(&dev->struct_mutex);
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- if (manager_ops && manager_ops->apply)
- if (!rockchip_encoder->updated)
- manager_ops->apply(manager->dev);
-
- rockchip_drm_connector_power(encoder, mode);
- rockchip_encoder->dpms = mode;
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- rockchip_drm_connector_power(encoder, mode);
- rockchip_encoder->dpms = mode;
- rockchip_encoder->updated = false;
- break;
- default:
- DRM_ERROR("unspecified mode %d\n", mode);
- break;
- }
-
- mutex_unlock(&dev->struct_mutex);
-}
-
-static bool
-rockchip_drm_encoder_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_connector *connector;
- struct rockchip_drm_manager *manager = rockchip_drm_get_manager(encoder);
- struct rockchip_drm_manager_ops *manager_ops = manager->ops;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder)
- if (manager_ops && manager_ops->mode_fixup)
- manager_ops->mode_fixup(manager->dev, connector,
- mode, adjusted_mode);
- }
-
- return true;
-}
-
-static void disable_plane_to_crtc(struct drm_device *dev,
- struct drm_crtc *old_crtc,
- struct drm_crtc *new_crtc)
-{
- struct drm_plane *plane;
-
- /*
- * if old_crtc isn't same as encoder->crtc then it means that
- * user changed crtc id to another one so the plane to old_crtc
- * should be disabled and plane->crtc should be set to new_crtc
- * (encoder->crtc)
- */
- list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
- if (plane->crtc == old_crtc) {
- /*
- * do not change below call order.
- *
- * plane->funcs->disable_plane call checks
- * if encoder->crtc is same as plane->crtc and if same
- * then overlay_ops->disable callback will be called
- * to diasble current hw overlay so plane->crtc should
- * have new_crtc because new_crtc was set to
- * encoder->crtc in advance.
- */
- plane->crtc = new_crtc;
- plane->funcs->disable_plane(plane);
- }
- }
-}
-
-static void rockchip_drm_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_connector *connector;
- struct rockchip_drm_manager *manager;
- struct rockchip_drm_manager_ops *manager_ops;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder) {
- struct rockchip_drm_encoder *rockchip_encoder;
-
- rockchip_encoder = to_rockchip_encoder(encoder);
-
- if (rockchip_encoder->old_crtc != encoder->crtc &&
- rockchip_encoder->old_crtc) {
-
- /*
- * disable a plane to old crtc and change
- * crtc of the plane to new one.
- */
- disable_plane_to_crtc(dev,
- rockchip_encoder->old_crtc,
- encoder->crtc);
- }
-
- manager = rockchip_drm_get_manager(encoder);
- manager_ops = manager->ops;
-
- if (manager_ops && manager_ops->mode_set)
- manager_ops->mode_set(manager->dev,
- adjusted_mode);
-
- rockchip_encoder->old_crtc = encoder->crtc;
- }
- }
-}
-
-static void rockchip_drm_encoder_prepare(struct drm_encoder *encoder)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* drm framework doesn't check NULL. */
-}
-
-static void rockchip_drm_encoder_commit(struct drm_encoder *encoder)
-{
- struct rockchip_drm_encoder *rockchip_encoder = to_rockchip_encoder(encoder);
- struct rockchip_drm_manager *manager = rockchip_encoder->manager;
- struct rockchip_drm_manager_ops *manager_ops = manager->ops;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (manager_ops && manager_ops->commit)
- manager_ops->commit(manager->dev);
-
- /*
- * this will avoid one issue that overlay data is updated to
- * real hardware two times.
- * And this variable will be used to check if the data was
- * already updated or not by rockchip_drm_encoder_dpms function.
- */
- rockchip_encoder->updated = true;
-
- /*
- * In case of setcrtc, there is no way to update encoder's dpms
- * so update it here.
- */
- rockchip_encoder->dpms = DRM_MODE_DPMS_ON;
-}
-
-void rockchip_drm_encoder_complete_scanout(struct drm_framebuffer *fb)
-{
- struct rockchip_drm_encoder *rockchip_encoder;
- struct rockchip_drm_manager_ops *ops;
- struct drm_device *dev = fb->dev;
- struct drm_encoder *encoder;
-
- /*
- * make sure that overlay data are updated to real hardware
- * for all encoders.
- */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- rockchip_encoder = to_rockchip_encoder(encoder);
- ops = rockchip_encoder->manager->ops;
-
- /*
- * wait for vblank interrupt
- * - this makes sure that overlay data are updated to
- * real hardware.
- */
- if (ops->wait_for_vblank)
- ops->wait_for_vblank(rockchip_encoder->manager->dev);
- }
-}
-
-
-static void rockchip_drm_encoder_disable(struct drm_encoder *encoder)
-{
- struct drm_plane *plane;
- struct drm_device *dev = encoder->dev;
-
- rockchip_drm_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-
- /* all planes connected to this encoder should be also disabled. */
- list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
- if (plane->crtc == encoder->crtc)
- plane->funcs->disable_plane(plane);
- }
-}
-
-static struct drm_encoder_helper_funcs rockchip_encoder_helper_funcs = {
- .dpms = rockchip_drm_encoder_dpms,
- .mode_fixup = rockchip_drm_encoder_mode_fixup,
- .mode_set = rockchip_drm_encoder_mode_set,
- .prepare = rockchip_drm_encoder_prepare,
- .commit = rockchip_drm_encoder_commit,
- .disable = rockchip_drm_encoder_disable,
-};
-
-static void rockchip_drm_encoder_destroy(struct drm_encoder *encoder)
-{
- struct rockchip_drm_encoder *rockchip_encoder =
- to_rockchip_encoder(encoder);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- rockchip_encoder->manager->pipe = -1;
-
- drm_encoder_cleanup(encoder);
- kfree(rockchip_encoder);
-}
-
-static struct drm_encoder_funcs rockchip_encoder_funcs = {
- .destroy = rockchip_drm_encoder_destroy,
-};
-
-static unsigned int rockchip_drm_encoder_clones(struct drm_encoder *encoder)
-{
- struct drm_encoder *clone;
- struct drm_device *dev = encoder->dev;
- struct rockchip_drm_encoder *rockchip_encoder = to_rockchip_encoder(encoder);
- struct rockchip_drm_display_ops *display_ops =
- rockchip_encoder->manager->display_ops;
- unsigned int clone_mask = 0;
- int cnt = 0;
-
- list_for_each_entry(clone, &dev->mode_config.encoder_list, head) {
- switch (display_ops->type) {
- case ROCKCHIP_DISPLAY_TYPE_LCD:
- case ROCKCHIP_DISPLAY_TYPE_HDMI:
- case ROCKCHIP_DISPLAY_TYPE_VIDI:
- clone_mask |= (1 << (cnt++));
- break;
- default:
- continue;
- }
- }
-
- return clone_mask;
-}
-
-void rockchip_drm_encoder_setup(struct drm_device *dev)
-{
- struct drm_encoder *encoder;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
- encoder->possible_clones = rockchip_drm_encoder_clones(encoder);
-}
-
-struct drm_encoder *
-rockchip_drm_encoder_create(struct drm_device *dev,
- struct rockchip_drm_manager *manager,
- unsigned int possible_crtcs)
-{
- struct drm_encoder *encoder;
- struct rockchip_drm_encoder *rockchip_encoder;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!manager || !possible_crtcs)
- return NULL;
-
- if (!manager->dev)
- return NULL;
-
- rockchip_encoder = kzalloc(sizeof(*rockchip_encoder), GFP_KERNEL);
- if (!rockchip_encoder) {
- DRM_ERROR("failed to allocate encoder\n");
- return NULL;
- }
-
- rockchip_encoder->dpms = DRM_MODE_DPMS_OFF;
- rockchip_encoder->manager = manager;
- encoder = &rockchip_encoder->drm_encoder;
- encoder->possible_crtcs = possible_crtcs;
-
- DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
-
- drm_encoder_init(dev, encoder, &rockchip_encoder_funcs,
- DRM_MODE_ENCODER_TMDS);
-
- drm_encoder_helper_add(encoder, &rockchip_encoder_helper_funcs);
-
- DRM_DEBUG_KMS("encoder has been created\n");
-
- return encoder;
-}
-
-struct rockchip_drm_manager *rockchip_drm_get_manager(struct drm_encoder *encoder)
-{
- return to_rockchip_encoder(encoder)->manager;
-}
-
-void rockchip_drm_fn_encoder(struct drm_crtc *crtc, void *data,
- void (*fn)(struct drm_encoder *, void *))
-{
- struct drm_device *dev = crtc->dev;
- struct drm_encoder *encoder;
- struct rockchip_drm_private *private = dev->dev_private;
- struct rockchip_drm_manager *manager;
-
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- /*
- * if crtc is detached from encoder, check pipe,
- * otherwise check crtc attached to encoder
- */
- if (!encoder->crtc) {
- manager = to_rockchip_encoder(encoder)->manager;
- if (manager->pipe < 0 ||
- private->crtc[manager->pipe] != crtc)
- continue;
- } else {
- if (encoder->crtc != crtc)
- continue;
- }
-
- fn(encoder, data);
- }
-}
-int rockchip_get_crtc_vblank_timestamp(struct drm_device *dev, int crtc,
- int *max_error,
- struct timeval *vblank_time,
- unsigned flags)
-{
-#if 0
- ktime_t stime, etime, mono_time_offset;
- struct timeval tv_etime;
- struct drm_display_mode *mode;
- int vbl_status, vtotal, vdisplay;
- int vpos, hpos, i;
- s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
- bool invbl;
-
- if (crtc < 0 || crtc >= dev->num_crtcs) {
- DRM_ERROR("Invalid crtc %d\n", crtc);
- return -EINVAL;
- }
-
- /* Scanout position query not supported? Should not happen. */
- if (!dev->driver->get_scanout_position) {
- DRM_ERROR("Called from driver w/o get_scanout_position()!?\n");
- return -EIO;
- }
-#endif
- return 0;//vbl_status;
-
-}
-void rockchip_drm_enable_vblank(struct drm_encoder *encoder, void *data)
-{
- struct rockchip_drm_manager *manager =
- to_rockchip_encoder(encoder)->manager;
- struct rockchip_drm_manager_ops *manager_ops = manager->ops;
- int crtc = *(int *)data;
-
- if (manager->pipe != crtc)
- return;
-
- if (manager_ops->enable_vblank)
- manager_ops->enable_vblank(manager->dev);
-}
-
-void rockchip_drm_disable_vblank(struct drm_encoder *encoder, void *data)
-{
- struct rockchip_drm_manager *manager =
- to_rockchip_encoder(encoder)->manager;
- struct rockchip_drm_manager_ops *manager_ops = manager->ops;
- int crtc = *(int *)data;
-
- if (manager->pipe != crtc)
- return;
-
- if (manager_ops->disable_vblank)
- manager_ops->disable_vblank(manager->dev);
-}
-
-void rockchip_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
-{
- struct rockchip_drm_encoder *rockchip_encoder = to_rockchip_encoder(encoder);
- struct rockchip_drm_manager *manager = rockchip_encoder->manager;
- struct rockchip_drm_manager_ops *manager_ops = manager->ops;
- int mode = *(int *)data;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (manager_ops && manager_ops->dpms)
- manager_ops->dpms(manager->dev, mode);
-
- /*
- * if this condition is ok then it means that the crtc is already
- * detached from encoder and last function for detaching is properly
- * done, so clear pipe from manager to prevent repeated call.
- */
- if (mode > DRM_MODE_DPMS_ON) {
- if (!encoder->crtc)
- manager->pipe = -1;
- }
-}
-
-void rockchip_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data)
-{
- struct rockchip_drm_manager *manager =
- to_rockchip_encoder(encoder)->manager;
- int pipe = *(int *)data;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * when crtc is detached from encoder, this pipe is used
- * to select manager operation
- */
- manager->pipe = pipe;
-}
-
-void rockchip_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
-{
- struct rockchip_drm_manager *manager =
- to_rockchip_encoder(encoder)->manager;
- struct rockchip_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- struct rockchip_drm_overlay *overlay = data;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (overlay_ops && overlay_ops->mode_set)
- overlay_ops->mode_set(manager->dev, overlay);
-}
-
-void rockchip_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
-{
- struct rockchip_drm_manager *manager =
- to_rockchip_encoder(encoder)->manager;
- struct rockchip_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- int zpos = DEFAULT_ZPOS;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (data)
- zpos = *(int *)data;
-
- if (overlay_ops && overlay_ops->commit)
- overlay_ops->commit(manager->dev, zpos);
-}
-
-void rockchip_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
-{
- struct rockchip_drm_manager *manager =
- to_rockchip_encoder(encoder)->manager;
- struct rockchip_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- int zpos = DEFAULT_ZPOS;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (data)
- zpos = *(int *)data;
-
- if (overlay_ops && overlay_ops->enable)
- overlay_ops->enable(manager->dev, zpos);
-}
-
-void rockchip_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
-{
- struct rockchip_drm_manager *manager =
- to_rockchip_encoder(encoder)->manager;
- struct rockchip_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- int zpos = DEFAULT_ZPOS;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (data)
- zpos = *(int *)data;
-
- if (overlay_ops && overlay_ops->disable)
- overlay_ops->disable(manager->dev, zpos);
-}
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_encoder.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#ifndef _ROCKCHIP_DRM_ENCODER_H_
-#define _ROCKCHIP_DRM_ENCODER_H_
-
-struct rockchip_drm_manager;
-
-void rockchip_drm_encoder_setup(struct drm_device *dev);
-struct drm_encoder *rockchip_drm_encoder_create(struct drm_device *dev,
- struct rockchip_drm_manager *mgr,
- unsigned int possible_crtcs);
-struct rockchip_drm_manager *
-rockchip_drm_get_manager(struct drm_encoder *encoder);
-void rockchip_drm_fn_encoder(struct drm_crtc *crtc, void *data,
- void (*fn)(struct drm_encoder *, void *));
-void rockchip_drm_enable_vblank(struct drm_encoder *encoder, void *data);
-void rockchip_drm_disable_vblank(struct drm_encoder *encoder, void *data);
-void rockchip_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data);
-void rockchip_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data);
-void rockchip_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data);
-void rockchip_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data);
-void rockchip_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data);
-void rockchip_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data);
-void rockchip_drm_encoder_complete_scanout(struct drm_framebuffer *fb);
-
-#endif
+++ /dev/null
-/*
- * rockchip_drm_extend.c
- *
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_fimd.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#include <drm/drmP.h>
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/of_device.h>
-#include <linux/pm_runtime.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_edid.h>
-
-#include <video/of_display_timing.h>
-#include <drm/rockchip_drm.h>
-#include <linux/rockchip/cpu.h>
-#include <linux/rockchip/iomap.h>
-#include <linux/rk_fb.h>
-#include <video/display_timing.h>
-#include <linux/rockchip/cpu.h>
-#include <linux/rockchip/iomap.h>
-#include <linux/rockchip/grf.h>
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_fbdev.h"
-#include "rockchip_drm_crtc.h"
-#include "rockchip_drm_iommu.h"
-#include "rockchip_drm_extend.h"
-static struct device *g_dev = NULL;
-static int extend_activate(struct extend_context *ctx, bool enable);
-#if 0
-extern struct void *get_extend_drv(void);
-#endif
-#if 0
-static const char fake_edid_info[] = {
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05,
- 0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78,
- 0x0a, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0xbd,
- 0xee, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x66, 0x21, 0x50, 0xb0, 0x51, 0x00,
- 0x1b, 0x30, 0x40, 0x70, 0x36, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e,
- 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
- 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18,
- 0x4b, 0x1a, 0x44, 0x17, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x00, 0x00, 0x00, 0xfc, 0x00, 0x53, 0x41, 0x4d, 0x53, 0x55, 0x4e, 0x47,
- 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xbc, 0x02, 0x03, 0x1e, 0xf1,
- 0x46, 0x84, 0x05, 0x03, 0x10, 0x20, 0x22, 0x23, 0x09, 0x07, 0x07, 0x83,
- 0x01, 0x00, 0x00, 0xe2, 0x00, 0x0f, 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00,
- 0xb8, 0x2d, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c,
- 0x25, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x9e, 0x8c, 0x0a, 0xd0, 0x8a,
- 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xa0, 0x5a, 0x00, 0x00,
- 0x00, 0x18, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
- 0x45, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06
-};
-#endif
-extern int primary_is_display;
-extern wait_queue_head_t wait_primary_queue;
-static bool extend_display_is_connected(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- DRM_DEBUG_KMS("%s\n", __FILE__);
- printk(KERN_ERR"%s %d\n", __func__,__LINE__);
-
- return drm_disp->is_connected?true:false;
-
- /* TODO. */
-}
-
-static void *extend_get_panel(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- struct list_head *pos;
- struct fb_modelist *modelist;
- struct fb_videomode *mode;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
- if(!drm_disp->is_connected)
- return NULL;
- list_for_each(pos,drm_disp->modelist){
- modelist = list_entry(pos, struct fb_modelist, list);
- mode = &modelist->mode;
- if(mode->flag == HDMI_VIDEO_DEFAULT_MODE)
- break;
- }
-
- memcpy(&ctx->panel->timing,mode,sizeof(struct fb_videomode));
-
- return ctx->panel;
-}
-static void *extend_get_modelist(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
- struct rk_drm_display *drm_disp = ctx->drm_disp;
-
- return drm_disp->modelist;
-}
-static int extend_check_timing(struct device *dev, void *timing)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- printk(KERN_ERR"%s %d\n", __func__,__LINE__);
- /* TODO. */
-
- return 0;
-}
-
-static int extend_display_power_on(struct device *dev, int mode)
-{
- struct extend_context *ctx = get_extend_context(dev);
- DRM_DEBUG_KMS("%s\n", __FILE__);
- /* TODO */
- printk(KERN_ERR"%s %d\n", __func__,__LINE__);
- extend_activate(ctx,mode == DRM_MODE_DPMS_ON?true:false);
-
- return 0;
-}
-struct edid *extend_get_edid(struct device *dev,
- struct drm_connector *connector)
-{
-#if 0
- int i, j = 0, valid_extensions = 0;
- struct hdmi *hdmi = get_extend_drv();
- u8 *block, *new;
- struct edid *edid = NULL;
- struct edid *raw_edid = NULL;
- bool print_bad_edid = !connector->bad_edid_counter;
-
- if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
- return NULL;
- /* base block fetch */
- for (i = 0; i < 4; i++) {
- if(hdmi->read_edid(hdmi, 0, block))
- goto out;
- if (drm_edid_block_valid(block, 0, print_bad_edid))
- break;
- }
- if (i == 4)
- goto carp;
-
- /* if there's no extensions, we're done */
- if (block[0x7e] == 0)
- return block;
-
- new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
- if (!new)
- goto out;
- block = new;
-
- for (j = 1; j <= block[0x7e]; j++) {
- for (i = 0; i < 4; i++) {
- if(hdmi->read_edid(hdmi, j, block))
- goto out;
- if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j, print_bad_edid)) {
- valid_extensions++;
- break;
- }
- }
-
- if (i == 4 && print_bad_edid) {
- dev_warn(connector->dev->dev,
- "%s: Ignoring invalid EDID block %d.\n",
- drm_get_connector_name(connector), j);
-
- connector->bad_edid_counter++;
- }
- }
-
- if (valid_extensions != block[0x7e]) {
- block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
- block[0x7e] = valid_extensions;
- new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
- if (!new)
- goto out;
- block = new;
- }
- edid = (struct edid *)block;
- return edid;
-
-carp:
- if (print_bad_edid) {
- dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
- drm_get_connector_name(connector), j);
- }
- connector->bad_edid_counter++;
-
-out:
- kfree(block);
- raw_edid = (struct edid *)fake_edid_info;
- edid = kmemdup(raw_edid, (1 + raw_edid->extensions) * EDID_LENGTH, GFP_KERNEL);
- if (!edid) {
- DRM_DEBUG_KMS("failed to allocate edid\n");
- return ERR_PTR(-ENOMEM);
- }
- return edid;
-#endif
-}
-
-static struct rockchip_drm_display_ops extend_display_ops = {
- .type = ROCKCHIP_DISPLAY_TYPE_HDMI,
- .is_connected = extend_display_is_connected,
- .get_panel = extend_get_panel,
- .get_modelist = extend_get_modelist,
- .check_timing = extend_check_timing,
- .power_on = extend_display_power_on,
-// .get_edid = extend_get_edid,
-};
-
-static void extend_dpms(struct device *subdrv_dev, int mode)
-{
- struct extend_context *ctx = get_extend_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
-
- mutex_lock(&ctx->lock);
-
- printk(KERN_ERR"%s %d\n", __func__,__LINE__);
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- /*
- * enable primary hardware only if suspended status.
- *
- * P.S. extend_dpms function would be called at booting time so
- * clk_enable could be called double time.
- */
-
- if (ctx->suspended)
- pm_runtime_get_sync(subdrv_dev);
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- if (!ctx->suspended)
- pm_runtime_put_sync(subdrv_dev);
- break;
- default:
- DRM_DEBUG_KMS("unspecified mode %d\n", mode);
- break;
- }
-
- mutex_unlock(&ctx->lock);
-}
-
-static void extend_apply(struct device *subdrv_dev)
-{
- struct extend_context *ctx = get_extend_context(subdrv_dev);
- struct rockchip_drm_manager *mgr = ctx->subdrv.manager;
- struct rockchip_drm_manager_ops *mgr_ops = mgr->ops;
- struct rockchip_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
- struct extend_win_data *win_data;
- int i;
-
- printk(KERN_ERR"%s %d\n", __func__,__LINE__);
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- for (i = 0; i < WINDOWS_NR; i++) {
- win_data = &ctx->win_data[i];
- if (win_data->enabled && (ovl_ops && ovl_ops->commit))
- ovl_ops->commit(subdrv_dev, i);
- }
-
- if (mgr_ops && mgr_ops->commit)
- mgr_ops->commit(subdrv_dev);
-}
-
-static void extend_commit(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- struct rockchip_drm_panel_info *panel = (struct rockchip_drm_panel_info *)extend_get_panel(dev);
-
-// printk(KERN_ERR"%s %d\n", __func__,__LINE__);
- if (ctx->suspended)
- return;
-
- drm_disp->mode = &panel->timing;
-
- drm_disp->enable = true;
- rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_SET);
-}
-
-static int extend_enable_vblank(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return -EPERM;
-
- ctx->vblank_en = true;
- return 0;
-}
-
-static void extend_disable_vblank(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return;
-
- ctx->vblank_en = false;
-}
-
-static void extend_wait_for_vblank(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
-
- if (ctx->suspended)
- return;
-#if 1
- atomic_set(&ctx->wait_vsync_event, 1);
-
- if (!wait_event_timeout(ctx->wait_vsync_queue,
- !atomic_read(&ctx->wait_vsync_event),
- DRM_HZ/20))
- DRM_DEBUG_KMS("vblank wait timed out.\n");
-#endif
-}
-
-static void extend_event_call_back_handle(struct rk_drm_display *drm_disp,int win_id,int event)
-{
- struct extend_context *ctx = get_extend_context(g_dev);
- struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
- struct rockchip_drm_manager *manager = subdrv->manager;
- struct drm_device *drm_dev = subdrv->drm_dev;
- switch(event){
- case RK_DRM_CALLBACK_VSYNC:
- /* check the crtc is detached already from encoder */
- if (manager->pipe < 0)
- return;
-
- drm_handle_vblank(drm_dev, manager->pipe);
- rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
-
- /* set wait vsync event to zero and wake up queue. */
- if (atomic_read(&ctx->wait_vsync_event)) {
- atomic_set(&ctx->wait_vsync_event, 0);
- DRM_WAKEUP(&ctx->wait_vsync_queue);
- }
- break;
- case RK_DRM_CALLBACK_HOTPLUG:
-#if 0
- if(0){//primary_is_display == 0){
- printk(KERN_ERR"-->%s waitfor hotplug event %d\n",__func__,event);
- int is_connected = drm_disp->is_connected;
- drm_disp->is_connected = false;
-
- if (!wait_event_timeout(wait_primary_queue,
- primary_is_display,
- 20*1000)){
- printk(KERN_ERR"-->%s waitfot hotplug event %d timeout\n",__func__,event);
- }
- drm_disp->is_connected = true;
- }
-#endif
- printk(KERN_ERR"-->%s hotplug event %d\n",__func__,event);
- drm_helper_hpd_irq_event(drm_dev);
- break;
-
- default:
- printk(KERN_ERR"-->%s unhandle event %d\n",__func__,event);
- break;
- }
-}
-static void extend_get_max_resol(void *ctx, unsigned int *width,
- unsigned int *height)
-{
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- *width = MAX_HDMI_WIDTH;
- *height = MAX_HDMI_HEIGHT;
-}
-static struct rockchip_drm_manager_ops extend_manager_ops = {
- .dpms = extend_dpms,
- .apply = extend_apply,
- .commit = extend_commit,
- .enable_vblank = extend_enable_vblank,
- .disable_vblank = extend_disable_vblank,
- .wait_for_vblank = extend_wait_for_vblank,
- .get_max_resol = extend_get_max_resol,
-};
-
-static void extend_win_mode_set(struct device *dev,
- struct rockchip_drm_overlay *overlay)
-{
- struct extend_context *ctx = get_extend_context(dev);
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- struct extend_win_data *win_data;
- int win;
- unsigned long offset;
- struct list_head *pos,*head;
- struct fb_modelist *modelist;
- struct fb_videomode *mode;
- struct drm_display_mode *disp_mode = NULL;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!overlay) {
- dev_err(dev, "overlay is NULL\n");
- return;
- }
-
- win = overlay->zpos;
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- offset = overlay->fb_x * (overlay->bpp >> 3);
- offset += overlay->fb_y * overlay->pitch;
-
-// printk("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
-// printk("crtc_x=%d crtc_y=%d crtc_width=%d crtc_height=%d\n",overlay->crtc_x,overlay->crtc_y,overlay->crtc_width,overlay->crtc_height);
-// printk("fb_width=%d fb_height=%d dma_addr=%x offset=%x\n",overlay->fb_width,overlay->fb_height,overlay->dma_addr[0],offset);
-
- win_data = &ctx->win_data[win];
-
- win_data->offset_x = overlay->crtc_x;
- win_data->offset_y = overlay->crtc_y;
- win_data->ovl_width = overlay->crtc_width;
- win_data->ovl_height = overlay->crtc_height;
- win_data->fb_width = overlay->fb_width;
- win_data->fb_height = overlay->fb_height;
- win_data->dma_addr = overlay->dma_addr[0] + offset;
- win_data->bpp = overlay->bpp;
- win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
- (overlay->bpp >> 3);
- win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
- head = drm_disp->modelist;
- list_for_each(pos,head){
- modelist = list_entry(pos, struct fb_modelist, list);
- mode = &modelist->mode;
- if(mode->xres == overlay->mode_width && mode->yres == overlay->mode_height
- && mode->pixclock == overlay->pixclock)
- break;
- }
- if(drm_disp->mode != mode){
- printk(KERN_ERR"%s %d\n", __func__,__LINE__);
- drm_disp->mode = mode;
- printk("overlay [%dx%d-%d] mode[%dx%d-%d]\n",overlay->mode_width,overlay->mode_height,overlay->pixclock,mode->xres,mode->yres,mode->pixclock);
-// printk("overlay->mode_width=%d overlay->mode_height=%d mode_width=%d mode_height=%d",overlay->mode_width,overlay->mode_height,mode->xres,mode->yres);
-
- drm_disp->enable = true;
- rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_SET);
- }
-
-
-}
-
-static void extend_win_set_pixfmt(struct device *dev, unsigned int win)
-{
- struct extend_context *ctx = get_extend_context(dev);
- struct extend_win_data *win_data = &ctx->win_data[win];
-}
-
-static void extend_win_set_colkey(struct device *dev, unsigned int win)
-{
-// struct extend_context *ctx = get_extend_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
-}
-
-ktime_t win_start;
-ktime_t win_end;
-ktime_t win_start1;
-ktime_t win_end1;
-static void extend_win_commit(struct device *dev, int zpos)
-{
- struct extend_context *ctx = get_extend_context(dev);
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- struct rk_win_data *rk_win = NULL;
- struct extend_win_data *win_data;
- int win = zpos;
- unsigned long val, size;
- u32 xpos, ypos;
-
- //printk(KERN_ERR"%s %d\n", __func__,__LINE__);
- if (ctx->suspended)
- return;
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
- if(win == 0){
- win_start = ktime_get();
- win_start = ktime_sub(win_start, win_end);
-// printk("user flip buffer time %dms\n", (int)ktime_to_ms(win_start));
- // win_start = ktime_get();
- }
- rk_win = &drm_disp->win[win];
- win_data = &ctx->win_data[win];
- switch(win_data->bpp){
- case 32:
- rk_win->format = ARGB888;
- break;
- case 24:
- rk_win->format = RGB888;
- break;
- case 16:
- rk_win->format = RGB565;
- break;
- default:
- printk("not support format %d\n",win_data->bpp);
- break;
- }
-
- rk_win->xpos = win_data->offset_x;
- rk_win->ypos = win_data->offset_y;
- rk_win->xact = win_data->ovl_width;
- rk_win->yact = win_data->ovl_height;
- rk_win->xsize = win_data->ovl_width;
- rk_win->ysize = win_data->ovl_height;
- rk_win->xvir = win_data->fb_width;
- rk_win->yrgb_addr = win_data->dma_addr;
- rk_win->enabled = true;
-
- rk_drm_disp_handle(drm_disp,1<<win,RK_DRM_WIN_COMMIT | RK_DRM_DISPLAY_COMMIT);
-
- win_data->enabled = true;
- if(win ==0){
- // win_end = ktime_get();
- // win_end = ktime_sub(win_end, win_start);
- // printk("flip buffer time %dus\n", (int)ktime_to_us(win_end));
- win_end = ktime_get();
- }
-}
-
-static void extend_win_disable(struct device *dev, int zpos)
-{
- struct extend_context *ctx = get_extend_context(dev);
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- struct extend_win_data *win_data;
- int win = zpos;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- win_data = &ctx->win_data[win];
-
- if (ctx->suspended) {
- /* do not resume this window*/
- win_data->resume = false;
- return;
- }
- drm_disp->win[win].enabled = false;
- rk_drm_disp_handle(drm_disp,1<<win,RK_DRM_WIN_COMMIT | RK_DRM_DISPLAY_COMMIT);
-
- win_data->enabled = false;
-}
-
-static struct rockchip_drm_overlay_ops extend_overlay_ops = {
- .mode_set = extend_win_mode_set,
- .commit = extend_win_commit,
- .disable = extend_win_disable,
-};
-
-static struct rockchip_drm_manager extend_manager = {
- .pipe = -1,
- .ops = &extend_manager_ops,
- .overlay_ops = &extend_overlay_ops,
- .display_ops = &extend_display_ops,
-};
-#if 0
-static irqreturn_t extend_irq_handler(int irq, void *dev_id)
-{
- struct extend_context *ctx = (struct extend_context *)dev_id;
- struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
- struct drm_device *drm_dev = subdrv->drm_dev;
- struct rockchip_drm_manager *manager = subdrv->manager;
- u32 intr0_reg;
-
-
-
- /* check the crtc is detached already from encoder */
- if (manager->pipe < 0)
- goto out;
-
- drm_handle_vblank(drm_dev, manager->pipe);
- rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
-
- /* set wait vsync event to zero and wake up queue. */
- if (atomic_read(&ctx->wait_vsync_event)) {
- atomic_set(&ctx->wait_vsync_event, 0);
- DRM_WAKEUP(&ctx->wait_vsync_queue);
- }
-out:
- return IRQ_HANDLED;
-}
-#endif
-static int extend_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * enable drm irq mode.
- * - with irq_enabled = 1, we can use the vblank feature.
- *
- * P.S. note that we wouldn't use drm irq handler but
- * just specific driver own one instead because
- * drm framework supports only one irq handler.
- */
- drm_dev->irq_enabled = 1;
-
- /*
- * with vblank_disable_allowed = 1, vblank interrupt will be disabled
- * by drm timer once a current process gives up ownership of
- * vblank event.(after drm_vblank_put function is called)
- */
- drm_dev->vblank_disable_allowed = 1;
-
- /* attach this sub driver to iommu mapping if supported. */
- if (is_drm_iommu_supported(drm_dev))
- drm_iommu_attach_device(drm_dev, dev);
-
- return 0;
-}
-
-static void extend_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* detach this sub driver from iommu mapping if supported. */
- if (is_drm_iommu_supported(drm_dev))
- drm_iommu_detach_device(drm_dev, dev);
-}
-
-
-static void extend_clear_win(struct extend_context *ctx, int win)
-{
- u32 val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
-}
-
-
-static void extend_window_suspend(struct device *dev)
-{
- struct extend_win_data *win_data = NULL;
- struct extend_context *ctx = get_extend_context(dev);
- int i;
-
- for (i = 0; i < WINDOWS_NR; i++) {
- win_data = &ctx->win_data[i];
- win_data->resume = win_data->enabled;
- extend_win_disable(dev, i);
- }
- extend_wait_for_vblank(dev);
-}
-
-static void extend_window_resume(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
- struct extend_win_data *win_data;
- int i;
-
- for (i = 0; i < WINDOWS_NR; i++) {
- win_data = &ctx->win_data[i];
- win_data->enabled = win_data->resume;
- win_data->resume = false;
- }
-}
-
-static int extend_activate(struct extend_context *ctx, bool enable)
-{
- struct device *dev = ctx->subdrv.dev;
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- if (enable) {
- int ret;
-
- ctx->suspended = false;
-
- drm_disp->enable = true;
-
- rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_BLANK);
-
- /* if vblank was enabled status, enable it again. */
- if (ctx->vblank_en)
- extend_enable_vblank(dev);
-
- extend_window_resume(dev);
- } else {
- extend_window_suspend(dev);
-
- drm_disp->enable = false;
-
- rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_BLANK);
-
- ctx->suspended = true;
- }
-
- return 0;
-}
-
-static int extend_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct extend_context *ctx;
- struct rockchip_drm_subdrv *subdrv;
- struct rockchip_drm_panel_info *panel;
- struct rk_drm_display *drm_display = NULL;
- int ret = -EINVAL;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- g_dev = dev;
- ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
-
- panel = devm_kzalloc(dev, sizeof(struct rockchip_drm_panel_info), GFP_KERNEL);
- ctx->panel = panel;
-
- drm_display = rk_drm_get_diplay(RK_DRM_EXTEND_SCREEN);
- ctx->drm_disp = drm_display;
- ctx->default_win = 0;
-
- drm_display->event_call_back = extend_event_call_back_handle;
-
- DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
- atomic_set(&ctx->wait_vsync_event, 0);
-
- subdrv = &ctx->subdrv;
-
- subdrv->dev = dev;
- subdrv->manager = &extend_manager;
- subdrv->probe = extend_subdrv_probe;
- subdrv->remove = extend_subdrv_remove;
-
- mutex_init(&ctx->lock);
-
- platform_set_drvdata(pdev, ctx);
-
- pm_runtime_enable(dev);
- pm_runtime_get_sync(dev);
-
- //extend_commit(dev);
- extend_activate(ctx, true);
-
- rockchip_drm_subdrv_register(subdrv);
-
- return 0;
-}
-
-static int extend_remove(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct extend_context *ctx = platform_get_drvdata(pdev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- rockchip_drm_subdrv_unregister(&ctx->subdrv);
-
- if (ctx->suspended)
- goto out;
-
- pm_runtime_set_suspended(dev);
- pm_runtime_put_sync(dev);
-
-out:
- pm_runtime_disable(dev);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int extend_suspend(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
-
- /*
- * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
- * called here, an error would be returned by that interface
- * because the usage_count of pm runtime is more than 1.
- */
- if (!pm_runtime_suspended(dev))
- return extend_activate(ctx, false);
-
- return 0;
-}
-
-static int extend_resume(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
-
- /*
- * if entered to sleep when lcd panel was on, the usage_count
- * of pm runtime would still be 1 so in this case, fimd driver
- * should be on directly not drawing on pm runtime interface.
- */
- if (!pm_runtime_suspended(dev)) {
- int ret;
-
- ret = extend_activate(ctx, true);
- if (ret < 0)
- return ret;
-
- /*
- * in case of dpms on(standby), extend_apply function will
- * be called by encoder's dpms callback to update fimd's
- * registers but in case of sleep wakeup, it's not.
- * so extend_apply function should be called at here.
- */
- extend_apply(dev);
- }
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int extend_runtime_suspend(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return extend_activate(ctx, false);
-}
-
-static int extend_runtime_resume(struct device *dev)
-{
- struct extend_context *ctx = get_extend_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return extend_activate(ctx, true);
-}
-#endif
-
-static const struct dev_pm_ops extend_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(extend_suspend, extend_resume)
- SET_RUNTIME_PM_OPS(extend_runtime_suspend, extend_runtime_resume, NULL)
-};
-
-struct platform_driver extend_platform_driver = {
- .probe = extend_probe,
- .remove = extend_remove,
- .driver = {
- .owner = THIS_MODULE,
- .name = "extend-display",
- .pm = &extend_pm_ops,
- },
-};
+++ /dev/null
-#include "../../../video/rockchip/rk_drm_fb.h"
-#include "../../../video/rockchip/hdmi/rk_hdmi.h"
-#define WINDOWS_NR 4
-#define MAX_HDMI_WIDTH 1920
-#define MAX_HDMI_HEIGHT 1080
-
-#define get_extend_context(dev) platform_get_drvdata(to_platform_device(dev))
-
-struct extend_win_data {
- unsigned int offset_x;
- unsigned int offset_y;
- unsigned int ovl_width;
- unsigned int ovl_height;
- unsigned int fb_width;
- unsigned int fb_height;
- unsigned int bpp;
- dma_addr_t dma_addr;
- unsigned int buf_offsize;
- unsigned int line_size; /* bytes */
- bool enabled;
- bool resume;
-};
-
-struct extend_context {
- struct rockchip_drm_subdrv subdrv;
- int vblank_en;
- struct drm_crtc *crtc;
- struct rk_drm_display *drm_disp;
- struct extend_win_data win_data[WINDOWS_NR];
- unsigned int default_win;
- bool suspended;
- struct mutex lock;
- wait_queue_head_t wait_vsync_queue;
- atomic_t wait_vsync_event;
-
- struct rockchip_drm_panel_info *panel;
-};
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_hdmi.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#include <drm/drmP.h>
-
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/rockchip_drm.h>
-
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_hdmi.h"
-
-#define to_context(dev) platform_get_drvdata(to_platform_device(dev))
-#define to_subdrv(dev) to_context(dev)
-#define get_ctx_from_subdrv(subdrv) container_of(subdrv,\
- struct drm_hdmi_context, subdrv);
-
-/* platform device pointer for common drm hdmi device. */
-static struct platform_device *rockchip_drm_hdmi_pdev;
-
-/* Common hdmi subdrv needs to access the hdmi and mixer though context.
-* These should be initialied by the repective drivers */
-static struct rockchip_drm_hdmi_context *hdmi_ctx;
-static struct rockchip_drm_hdmi_context *mixer_ctx;
-
-/* these callback points shoud be set by specific drivers. */
-static struct rockchip_hdmi_ops *hdmi_ops;
-static struct rockchip_mixer_ops *mixer_ops;
-
-struct drm_hdmi_context {
- struct rockchip_drm_subdrv subdrv;
- struct rockchip_drm_hdmi_context *hdmi_ctx;
- struct rockchip_drm_hdmi_context *mixer_ctx;
-
- bool enabled[MIXER_WIN_NR];
-};
-
-int rockchip_platform_device_hdmi_register(void)
-{
- struct platform_device *pdev;
-
- if (rockchip_drm_hdmi_pdev)
- return -EEXIST;
-
- pdev = platform_device_register_simple(
- "rockchip-drm-hdmi", -1, NULL, 0);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- rockchip_drm_hdmi_pdev = pdev;
-
- return 0;
-}
-
-void rockchip_platform_device_hdmi_unregister(void)
-{
- if (rockchip_drm_hdmi_pdev) {
- platform_device_unregister(rockchip_drm_hdmi_pdev);
- rockchip_drm_hdmi_pdev = NULL;
- }
-}
-
-void rockchip_hdmi_drv_attach(struct rockchip_drm_hdmi_context *ctx)
-{
- if (ctx)
- hdmi_ctx = ctx;
-}
-
-void rockchip_mixer_drv_attach(struct rockchip_drm_hdmi_context *ctx)
-{
- if (ctx)
- mixer_ctx = ctx;
-}
-
-void rockchip_hdmi_ops_register(struct rockchip_hdmi_ops *ops)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ops)
- hdmi_ops = ops;
-}
-
-void rockchip_mixer_ops_register(struct rockchip_mixer_ops *ops)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ops)
- mixer_ops = ops;
-}
-
-static bool drm_hdmi_is_connected(struct device *dev)
-{
- struct drm_hdmi_context *ctx = to_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->is_connected)
- return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);
-
- return false;
-}
-
-static struct edid *drm_hdmi_get_edid(struct device *dev,
- struct drm_connector *connector)
-{
- struct drm_hdmi_context *ctx = to_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->get_edid)
- return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
-
- return NULL;
-}
-
-static int drm_hdmi_check_timing(struct device *dev, void *timing)
-{
- struct drm_hdmi_context *ctx = to_context(dev);
- int ret = 0;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * Both, mixer and hdmi should be able to handle the requested mode.
- * If any of the two fails, return mode as BAD.
- */
-
- if (mixer_ops && mixer_ops->check_timing)
- ret = mixer_ops->check_timing(ctx->mixer_ctx->ctx, timing);
-
- if (ret)
- return ret;
-
- if (hdmi_ops && hdmi_ops->check_timing)
- return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);
-
- return 0;
-}
-
-static int drm_hdmi_power_on(struct device *dev, int mode)
-{
- struct drm_hdmi_context *ctx = to_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->power_on)
- return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode);
-
- return 0;
-}
-
-static struct rockchip_drm_display_ops drm_hdmi_display_ops = {
- .type = ROCKCHIP_DISPLAY_TYPE_HDMI,
- .is_connected = drm_hdmi_is_connected,
- .get_edid = drm_hdmi_get_edid,
- .check_timing = drm_hdmi_check_timing,
- .power_on = drm_hdmi_power_on,
-};
-
-static int drm_hdmi_enable_vblank(struct device *subdrv_dev)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
- struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
- struct rockchip_drm_manager *manager = subdrv->manager;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (mixer_ops && mixer_ops->enable_vblank)
- return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx,
- manager->pipe);
-
- return 0;
-}
-
-static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (mixer_ops && mixer_ops->disable_vblank)
- return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
-}
-
-static void drm_hdmi_wait_for_vblank(struct device *subdrv_dev)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (mixer_ops && mixer_ops->wait_for_vblank)
- mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
-}
-
-static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
- struct drm_connector *connector,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_display_mode *m;
- int mode_ok;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- drm_mode_set_crtcinfo(adjusted_mode, 0);
-
- mode_ok = drm_hdmi_check_timing(subdrv_dev, adjusted_mode);
-
- /* just return if user desired mode exists. */
- if (mode_ok == 0)
- return;
-
- /*
- * otherwise, find the most suitable mode among modes and change it
- * to adjusted_mode.
- */
- list_for_each_entry(m, &connector->modes, head) {
- mode_ok = drm_hdmi_check_timing(subdrv_dev, m);
-
- if (mode_ok == 0) {
- struct drm_mode_object base;
- struct list_head head;
-
- DRM_INFO("desired mode doesn't exist so\n");
- DRM_INFO("use the most suitable mode among modes.\n");
-
- DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
- m->hdisplay, m->vdisplay, m->vrefresh);
-
- /* preserve display mode header while copying. */
- head = adjusted_mode->head;
- base = adjusted_mode->base;
- memcpy(adjusted_mode, m, sizeof(*m));
- adjusted_mode->head = head;
- adjusted_mode->base = base;
- break;
- }
- }
-}
-
-static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->mode_set)
- hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
-}
-
-static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
- unsigned int *width, unsigned int *height)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->get_max_resol)
- hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
-}
-
-static void drm_hdmi_commit(struct device *subdrv_dev)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->commit)
- hdmi_ops->commit(ctx->hdmi_ctx->ctx);
-}
-
-static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (mixer_ops && mixer_ops->dpms)
- mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
-
- if (hdmi_ops && hdmi_ops->dpms)
- hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
-}
-
-static void drm_hdmi_apply(struct device *subdrv_dev)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
- int i;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- for (i = 0; i < MIXER_WIN_NR; i++) {
- if (!ctx->enabled[i])
- continue;
- if (mixer_ops && mixer_ops->win_commit)
- mixer_ops->win_commit(ctx->mixer_ctx->ctx, i);
- }
-
- if (hdmi_ops && hdmi_ops->commit)
- hdmi_ops->commit(ctx->hdmi_ctx->ctx);
-}
-
-static struct rockchip_drm_manager_ops drm_hdmi_manager_ops = {
- .dpms = drm_hdmi_dpms,
- .apply = drm_hdmi_apply,
- .enable_vblank = drm_hdmi_enable_vblank,
- .disable_vblank = drm_hdmi_disable_vblank,
- .wait_for_vblank = drm_hdmi_wait_for_vblank,
- .mode_fixup = drm_hdmi_mode_fixup,
- .mode_set = drm_hdmi_mode_set,
- .get_max_resol = drm_hdmi_get_max_resol,
- .commit = drm_hdmi_commit,
-};
-
-static void drm_mixer_mode_set(struct device *subdrv_dev,
- struct rockchip_drm_overlay *overlay)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (mixer_ops && mixer_ops->win_mode_set)
- mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
-}
-
-static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
- int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (win < 0 || win > MIXER_WIN_NR) {
- DRM_ERROR("mixer window[%d] is wrong\n", win);
- return;
- }
-
- if (mixer_ops && mixer_ops->win_commit)
- mixer_ops->win_commit(ctx->mixer_ctx->ctx, win);
-
- ctx->enabled[win] = true;
-}
-
-static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
- int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (win < 0 || win > MIXER_WIN_NR) {
- DRM_ERROR("mixer window[%d] is wrong\n", win);
- return;
- }
-
- if (mixer_ops && mixer_ops->win_disable)
- mixer_ops->win_disable(ctx->mixer_ctx->ctx, win);
-
- ctx->enabled[win] = false;
-}
-
-static struct rockchip_drm_overlay_ops drm_hdmi_overlay_ops = {
- .mode_set = drm_mixer_mode_set,
- .commit = drm_mixer_commit,
- .disable = drm_mixer_disable,
-};
-
-static struct rockchip_drm_manager hdmi_manager = {
- .pipe = -1,
- .ops = &drm_hdmi_manager_ops,
- .overlay_ops = &drm_hdmi_overlay_ops,
- .display_ops = &drm_hdmi_display_ops,
-};
-
-static int hdmi_subdrv_probe(struct drm_device *drm_dev,
- struct device *dev)
-{
- struct rockchip_drm_subdrv *subdrv = to_subdrv(dev);
- struct drm_hdmi_context *ctx;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!hdmi_ctx) {
- DRM_ERROR("hdmi context not initialized.\n");
- return -EFAULT;
- }
-
- if (!mixer_ctx) {
- DRM_ERROR("mixer context not initialized.\n");
- return -EFAULT;
- }
-
- ctx = get_ctx_from_subdrv(subdrv);
-
- if (!ctx) {
- DRM_ERROR("no drm hdmi context.\n");
- return -EFAULT;
- }
-
- ctx->hdmi_ctx = hdmi_ctx;
- ctx->mixer_ctx = mixer_ctx;
-
- ctx->hdmi_ctx->drm_dev = drm_dev;
- ctx->mixer_ctx->drm_dev = drm_dev;
-
- if (mixer_ops->iommu_on)
- mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true);
-
- return 0;
-}
-
-static void hdmi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
-{
- struct drm_hdmi_context *ctx;
- struct rockchip_drm_subdrv *subdrv = to_subdrv(dev);
-
- ctx = get_ctx_from_subdrv(subdrv);
-
- if (mixer_ops->iommu_on)
- mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false);
-}
-
-static int rockchip_drm_hdmi_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct rockchip_drm_subdrv *subdrv;
- struct drm_hdmi_context *ctx;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
- if (!ctx) {
- DRM_LOG_KMS("failed to alloc common hdmi context.\n");
- return -ENOMEM;
- }
-
- subdrv = &ctx->subdrv;
-
- subdrv->dev = dev;
- subdrv->manager = &hdmi_manager;
- subdrv->probe = hdmi_subdrv_probe;
- subdrv->remove = hdmi_subdrv_remove;
-
- platform_set_drvdata(pdev, subdrv);
-
- rockchip_drm_subdrv_register(subdrv);
-
- return 0;
-}
-
-static int rockchip_drm_hdmi_remove(struct platform_device *pdev)
-{
- struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- rockchip_drm_subdrv_unregister(&ctx->subdrv);
-
- return 0;
-}
-
-struct platform_driver rockchip_drm_common_hdmi_driver = {
- .probe = rockchip_drm_hdmi_probe,
- .remove = rockchip_drm_hdmi_remove,
- .driver = {
- .name = "rockchip-drm-hdmi",
- .owner = THIS_MODULE,
- },
-};
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_hdmi.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#ifndef _ROCKCHIP_DRM_HDMI_H_
-#define _ROCKCHIP_DRM_HDMI_H_
-
-#define MIXER_WIN_NR 3
-#define MIXER_DEFAULT_WIN 0
-
-/*
- * rockchip hdmi common context structure.
- *
- * @drm_dev: pointer to drm_device.
- * @ctx: pointer to the context of specific device driver.
- * this context should be hdmi_context or mixer_context.
- */
-struct rockchip_drm_hdmi_context {
- struct drm_device *drm_dev;
- void *ctx;
-};
-
-struct rockchip_hdmi_ops {
- /* display */
- bool (*is_connected)(void *ctx);
- struct edid *(*get_edid)(void *ctx,
- struct drm_connector *connector);
- int (*check_timing)(void *ctx, struct fb_videomode *timing);
- int (*power_on)(void *ctx, int mode);
-
- /* manager */
- void (*mode_set)(void *ctx, void *mode);
- void (*get_max_resol)(void *ctx, unsigned int *width,
- unsigned int *height);
- void (*commit)(void *ctx);
- void (*dpms)(void *ctx, int mode);
-};
-
-struct rockchip_mixer_ops {
- /* manager */
- int (*iommu_on)(void *ctx, bool enable);
- int (*enable_vblank)(void *ctx, int pipe);
- void (*disable_vblank)(void *ctx);
- void (*wait_for_vblank)(void *ctx);
- void (*dpms)(void *ctx, int mode);
-
- /* overlay */
- void (*win_mode_set)(void *ctx, struct rockchip_drm_overlay *overlay);
- void (*win_commit)(void *ctx, int zpos);
- void (*win_disable)(void *ctx, int zpos);
-
- /* display */
- int (*check_timing)(void *ctx, struct fb_videomode *timing);
-};
-
-void rockchip_hdmi_drv_attach(struct rockchip_drm_hdmi_context *ctx);
-void rockchip_mixer_drv_attach(struct rockchip_drm_hdmi_context *ctx);
-void rockchip_hdmi_ops_register(struct rockchip_hdmi_ops *ops);
-void rockchip_mixer_ops_register(struct rockchip_mixer_ops *ops);
-#endif
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_iommu.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#include <drmP.h>
-#include <drm/rockchip_drm.h>
-
-#include <linux/dma-mapping.h>
-#include <linux/iommu.h>
-#include <linux/kref.h>
-
-#include <asm/dma-iommu.h>
-
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_iommu.h"
-
-/*
- * drm_create_iommu_mapping - create a mapping structure
- *
- * @drm_dev: DRM device
- */
-int drm_create_iommu_mapping(struct drm_device *drm_dev)
-{
- struct dma_iommu_mapping *mapping = NULL;
- struct rockchip_drm_private *priv = drm_dev->dev_private;
- struct device *dev = drm_dev->dev;
-
- if (!priv->da_start)
- priv->da_start = ROCKCHIP_DEV_ADDR_START;
- if (!priv->da_space_size)
- priv->da_space_size = ROCKCHIP_DEV_ADDR_SIZE;
- if (!priv->da_space_order)
- priv->da_space_order = ROCKCHIP_DEV_ADDR_ORDER;
-
- mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start,
- priv->da_space_size,
- priv->da_space_order);
- if (IS_ERR(mapping))
- return PTR_ERR(mapping);
-
- dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
- GFP_KERNEL);
- dma_set_max_seg_size(dev, 0xffffffffu);
- dev->archdata.mapping = mapping;
-
- return 0;
-}
-
-/*
- * drm_release_iommu_mapping - release iommu mapping structure
- *
- * @drm_dev: DRM device
- *
- * if mapping->kref becomes 0 then all things related to iommu mapping
- * will be released
- */
-void drm_release_iommu_mapping(struct drm_device *drm_dev)
-{
- struct device *dev = drm_dev->dev;
-
- arm_iommu_release_mapping(dev->archdata.mapping);
-}
-
-/*
- * drm_iommu_attach_device- attach device to iommu mapping
- *
- * @drm_dev: DRM device
- * @subdrv_dev: device to be attach
- *
- * This function should be called by sub drivers to attach it to iommu
- * mapping.
- */
-int drm_iommu_attach_device(struct drm_device *drm_dev,
- struct device *subdrv_dev)
-{
- struct device *dev = drm_dev->dev;
- int ret;
-
- if (!dev->archdata.mapping) {
- DRM_ERROR("iommu_mapping is null.\n");
- return -EFAULT;
- }
-
- subdrv_dev->dma_parms = devm_kzalloc(subdrv_dev,
- sizeof(*subdrv_dev->dma_parms),
- GFP_KERNEL);
- dma_set_max_seg_size(subdrv_dev, 0xffffffffu);
-
- ret = arm_iommu_attach_device(subdrv_dev, dev->archdata.mapping);
- if (ret < 0) {
- DRM_DEBUG_KMS("failed iommu attach.\n");
- return ret;
- }
-
- /*
- * Set dma_ops to drm_device just one time.
- *
- * The dma mapping api needs device object and the api is used
- * to allocate physial memory and map it with iommu table.
- * If iommu attach succeeded, the sub driver would have dma_ops
- * for iommu and also all sub drivers have same dma_ops.
- */
- if (!dev->archdata.dma_ops)
- dev->archdata.dma_ops = subdrv_dev->archdata.dma_ops;
-
- return 0;
-}
-
-/*
- * drm_iommu_detach_device -detach device address space mapping from device
- *
- * @drm_dev: DRM device
- * @subdrv_dev: device to be detached
- *
- * This function should be called by sub drivers to detach it from iommu
- * mapping
- */
-void drm_iommu_detach_device(struct drm_device *drm_dev,
- struct device *subdrv_dev)
-{
- struct device *dev = drm_dev->dev;
- struct dma_iommu_mapping *mapping = dev->archdata.mapping;
-
- if (!mapping || !mapping->domain)
- return;
-
- iommu_detach_device(mapping->domain, subdrv_dev);
- drm_release_iommu_mapping(drm_dev);
-}
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_iommu.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#ifndef _ROCKCHIP_DRM_IOMMU_H_
-#define _ROCKCHIP_DRM_IOMMU_H_
-
-#define ROCKCHIP_DEV_ADDR_START 0x20000000
-#define ROCKCHIP_DEV_ADDR_SIZE 0x40000000
-#define ROCKCHIP_DEV_ADDR_ORDER 0x0
-
-#ifdef CONFIG_DRM_ROCKCHIP_IOMMU
-
-int drm_create_iommu_mapping(struct drm_device *drm_dev);
-
-void drm_release_iommu_mapping(struct drm_device *drm_dev);
-
-int drm_iommu_attach_device(struct drm_device *drm_dev,
- struct device *subdrv_dev);
-
-void drm_iommu_detach_device(struct drm_device *dev_dev,
- struct device *subdrv_dev);
-
-static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
-{
-#ifdef CONFIG_ARM_DMA_USE_IOMMU
- struct device *dev = drm_dev->dev;
-
- return dev->archdata.mapping ? true : false;
-#else
- return false;
-#endif
-}
-
-#else
-
-struct dma_iommu_mapping;
-static inline int drm_create_iommu_mapping(struct drm_device *drm_dev)
-{
- return 0;
-}
-
-static inline void drm_release_iommu_mapping(struct drm_device *drm_dev)
-{
-}
-
-static inline int drm_iommu_attach_device(struct drm_device *drm_dev,
- struct device *subdrv_dev)
-{
- return 0;
-}
-
-static inline void drm_iommu_detach_device(struct drm_device *drm_dev,
- struct device *subdrv_dev)
-{
-}
-
-static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
-{
- return false;
-}
-
-#endif
-#endif
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_plane.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#include <drm/drmP.h>
-
-#include <drm/rockchip_drm.h>
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_encoder.h"
-#include "rockchip_drm_fb.h"
-#include "rockchip_drm_gem.h"
-
-#define to_rockchip_plane(x) container_of(x, struct rockchip_plane, base)
-
-struct rockchip_plane {
- struct drm_plane base;
- struct rockchip_drm_overlay overlay;
- bool enabled;
-};
-
-static const uint32_t formats[] = {
- DRM_FORMAT_XRGB8888,
- DRM_FORMAT_ARGB8888,
- DRM_FORMAT_NV12,
- DRM_FORMAT_NV12MT,
-};
-
-/*
- * This function is to get X or Y size shown via screen. This needs length and
- * start position of CRTC.
- *
- * <--- length --->
- * CRTC ----------------
- * ^ start ^ end
- *
- * There are six cases from a to f.
- *
- * <----- SCREEN ----->
- * 0 last
- * ----------|------------------|----------
- * CRTCs
- * a -------
- * b -------
- * c --------------------------
- * d --------
- * e -------
- * f -------
- */
-static int rockchip_plane_get_size(int start, unsigned length, unsigned last)
-{
- int end = start + length;
- int size = 0;
-
- if (start <= 0) {
- if (end > 0)
- size = min_t(unsigned, end, last);
- } else if (start <= last) {
- size = min_t(unsigned, last - start, length);
- }
-
- return size;
-}
-
-int rockchip_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
-{
- struct rockchip_plane *rockchip_plane = to_rockchip_plane(plane);
- struct rockchip_drm_overlay *overlay = &rockchip_plane->overlay;
- unsigned int actual_w;
- unsigned int actual_h;
- int nr;
- int i;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- nr = rockchip_drm_fb_get_buf_cnt(fb);
- for (i = 0; i < nr; i++) {
- struct rockchip_drm_gem_buf *buffer = rockchip_drm_fb_buffer(fb, i);
-
- if (!buffer) {
- DRM_LOG_KMS("buffer is null\n");
- return -EFAULT;
- }
-
- overlay->dma_addr[i] = buffer->dma_addr;
-
- DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n",
- i, (unsigned long)overlay->dma_addr[i]);
- }
-
- actual_w = rockchip_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay);
- actual_h = rockchip_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay);
-
- if (crtc_x < 0) {
- if (actual_w)
- src_x -= crtc_x;
- crtc_x = 0;
- }
-
- if (crtc_y < 0) {
- if (actual_h)
- src_y -= crtc_y;
- crtc_y = 0;
- }
-
- /* set drm framebuffer data. */
- overlay->fb_x = src_x;
- overlay->fb_y = src_y;
- overlay->fb_width = fb->width;
- overlay->fb_height = fb->height;
- overlay->src_width = src_w;
- overlay->src_height = src_h;
- overlay->bpp = fb->bits_per_pixel;
- overlay->pitch = fb->pitches[0];
- overlay->pixel_format = fb->pixel_format;
-
- /* set overlay range to be displayed. */
- overlay->crtc_x = crtc_x;
- overlay->crtc_y = crtc_y;
- overlay->crtc_width = actual_w;
- overlay->crtc_height = actual_h;
-
- /* set drm mode data. */
- overlay->mode_width = crtc->mode.hdisplay;
- overlay->mode_height = crtc->mode.vdisplay;
- overlay->refresh = crtc->mode.vrefresh;
- overlay->pixclock = crtc->mode.clock*1000;
- overlay->scan_flag = crtc->mode.flags;
-
-// printk("--->yzq %s crtc->mode->refresh =%d \n",__func__,crtc->mode.vrefresh);
- DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
- overlay->crtc_x, overlay->crtc_y,
- overlay->crtc_width, overlay->crtc_height);
-
- rockchip_drm_fn_encoder(crtc, overlay, rockchip_drm_encoder_plane_mode_set);
-
- return 0;
-}
-
-void rockchip_plane_commit(struct drm_plane *plane)
-{
- struct rockchip_plane *rockchip_plane = to_rockchip_plane(plane);
- struct rockchip_drm_overlay *overlay = &rockchip_plane->overlay;
-
- rockchip_drm_fn_encoder(plane->crtc, &overlay->zpos,
- rockchip_drm_encoder_plane_commit);
-}
-
-void rockchip_plane_dpms(struct drm_plane *plane, int mode)
-{
- struct rockchip_plane *rockchip_plane = to_rockchip_plane(plane);
- struct rockchip_drm_overlay *overlay = &rockchip_plane->overlay;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- if (mode == DRM_MODE_DPMS_ON) {
- if (rockchip_plane->enabled)
- return;
-
- rockchip_drm_fn_encoder(plane->crtc, &overlay->zpos,
- rockchip_drm_encoder_plane_enable);
-
- rockchip_plane->enabled = true;
- } else {
- if (!rockchip_plane->enabled)
- return;
-
- rockchip_drm_fn_encoder(plane->crtc, &overlay->zpos,
- rockchip_drm_encoder_plane_disable);
-
- rockchip_plane->enabled = false;
- }
-}
-
-static int
-rockchip_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
-{
- int ret;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- ret = rockchip_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
- crtc_w, crtc_h, src_x >> 16, src_y >> 16,
- src_w >> 16, src_h >> 16);
- if (ret < 0)
- return ret;
-
- plane->crtc = crtc;
-
- rockchip_plane_commit(plane);
- rockchip_plane_dpms(plane, DRM_MODE_DPMS_ON);
-
- return 0;
-}
-
-static int rockchip_disable_plane(struct drm_plane *plane)
-{
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- rockchip_plane_dpms(plane, DRM_MODE_DPMS_OFF);
-
- return 0;
-}
-
-static void rockchip_plane_destroy(struct drm_plane *plane)
-{
- struct rockchip_plane *rockchip_plane = to_rockchip_plane(plane);
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- rockchip_disable_plane(plane);
- drm_plane_cleanup(plane);
- kfree(rockchip_plane);
-}
-
-static int rockchip_plane_set_property(struct drm_plane *plane,
- struct drm_property *property,
- uint64_t val)
-{
- struct drm_device *dev = plane->dev;
- struct rockchip_plane *rockchip_plane = to_rockchip_plane(plane);
- struct rockchip_drm_private *dev_priv = dev->dev_private;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- if (property == dev_priv->plane_zpos_property) {
- rockchip_plane->overlay.zpos = val;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static struct drm_plane_funcs rockchip_plane_funcs = {
- .update_plane = rockchip_update_plane,
- .disable_plane = rockchip_disable_plane,
- .destroy = rockchip_plane_destroy,
- .set_property = rockchip_plane_set_property,
-};
-
-static void rockchip_plane_attach_zpos_property(struct drm_plane *plane)
-{
- struct drm_device *dev = plane->dev;
- struct rockchip_drm_private *dev_priv = dev->dev_private;
- struct drm_property *prop;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- prop = dev_priv->plane_zpos_property;
- if (!prop) {
- prop = drm_property_create_range(dev, 0, "zpos", 0,
- MAX_PLANE - 1);
- if (!prop)
- return;
-
- dev_priv->plane_zpos_property = prop;
- }
-
- drm_object_attach_property(&plane->base, prop, 0);
-}
-
-struct drm_plane *rockchip_plane_init(struct drm_device *dev,
- unsigned int possible_crtcs, bool priv)
-{
- struct rockchip_plane *rockchip_plane;
- int err;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- rockchip_plane = kzalloc(sizeof(struct rockchip_plane), GFP_KERNEL);
- if (!rockchip_plane) {
- DRM_ERROR("failed to allocate plane\n");
- return NULL;
- }
-
- err = drm_plane_init(dev, &rockchip_plane->base, possible_crtcs,
- &rockchip_plane_funcs, formats, ARRAY_SIZE(formats),
- priv);
- if (err) {
- DRM_ERROR("failed to initialize plane\n");
- kfree(rockchip_plane);
- return NULL;
- }
-
- if (priv)
- rockchip_plane->overlay.zpos = DEFAULT_ZPOS;
- else
- rockchip_plane_attach_zpos_property(&rockchip_plane->base);
-
- return &rockchip_plane->base;
-}
+++ /dev/null
-/*
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_plane.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-int rockchip_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h);
-void rockchip_plane_commit(struct drm_plane *plane);
-void rockchip_plane_dpms(struct drm_plane *plane, int mode);
-struct drm_plane *rockchip_plane_init(struct drm_device *dev,
- unsigned int possible_crtcs, bool priv);
+++ /dev/null
-/*
- * rockchip_drm_primary.c
- *
- * Copyright (C) ROCKCHIP, Inc.
- * Author:yzq<yzq@rock-chips.com>
- *
- * based on exynos_drm_fimd.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#include <drm/drmP.h>
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/of_device.h>
-#include <linux/pm_runtime.h>
-
-#include <video/of_display_timing.h>
-#include <drm/rockchip_drm.h>
-#include <linux/rockchip/cpu.h>
-#include <linux/rockchip/iomap.h>
-#include <linux/rk_fb.h>
-#include <video/display_timing.h>
-#include <linux/rockchip/cpu.h>
-#include <linux/rockchip/iomap.h>
-#include <linux/rockchip/grf.h>
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_fbdev.h"
-#include "rockchip_drm_crtc.h"
-#include "rockchip_drm_iommu.h"
-#include "rockchip_drm_primary.h"
-static struct device *g_dev = NULL;
-
-static bool primary_display_is_connected(struct device *dev)
-{
-
- /* TODO. */
-
- return false;
-}
-
-static void *primary_get_panel(struct device *dev)
-{
- struct primary_context *ctx = get_primary_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return ctx->panel;
-}
-
-static int primary_check_timing(struct device *dev, void *timing)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO. */
-
- return 0;
-}
-
-static int primary_display_power_on(struct device *dev, int mode)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO */
-
- return 0;
-}
-
-static struct rockchip_drm_display_ops primary_display_ops = {
- .type = ROCKCHIP_DISPLAY_TYPE_LCD,
- .is_connected = primary_display_is_connected,
- .get_panel = primary_get_panel,
- .check_timing = primary_check_timing,
- .power_on = primary_display_power_on,
-};
-
-static void primary_dpms(struct device *subdrv_dev, int mode)
-{
- struct primary_context *ctx = get_primary_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
-
- mutex_lock(&ctx->lock);
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- /*
- * enable primary hardware only if suspended status.
- *
- * P.S. primary_dpms function would be called at booting time so
- * clk_enable could be called double time.
- */
-
- if (ctx->suspended)
- pm_runtime_get_sync(subdrv_dev);
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- if (!ctx->suspended)
- pm_runtime_put_sync(subdrv_dev);
- break;
- default:
- DRM_DEBUG_KMS("unspecified mode %d\n", mode);
- break;
- }
-
- mutex_unlock(&ctx->lock);
-}
-
-static void primary_apply(struct device *subdrv_dev)
-{
- struct primary_context *ctx = get_primary_context(subdrv_dev);
- struct rockchip_drm_manager *mgr = ctx->subdrv.manager;
- struct rockchip_drm_manager_ops *mgr_ops = mgr->ops;
- struct rockchip_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
- struct primary_win_data *win_data;
- int i;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- for (i = 0; i < WINDOWS_NR; i++) {
- win_data = &ctx->win_data[i];
- if (win_data->enabled && (ovl_ops && ovl_ops->commit))
- ovl_ops->commit(subdrv_dev, i);
- }
-
- if (mgr_ops && mgr_ops->commit)
- mgr_ops->commit(subdrv_dev);
-}
-
-static void primary_commit(struct device *dev)
-{
- struct primary_context *ctx = get_primary_context(dev);
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- struct rockchip_drm_panel_info *panel = (struct rockchip_drm_panel_info *)primary_get_panel(dev);
- struct fb_videomode *mode;
-
- printk(KERN_ERR"%s %d\n", __func__,__LINE__);
- if (ctx->suspended)
- return;
- drm_disp->mode = &panel->timing;
- drm_disp->enable = true;
- rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_SET);
-}
-
-static int primary_enable_vblank(struct device *dev)
-{
- struct primary_context *ctx = get_primary_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return -EPERM;
-
- return 0;
-}
-
-static void primary_disable_vblank(struct device *dev)
-{
- struct primary_context *ctx = get_primary_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return;
-}
-
-static void primary_wait_for_vblank(struct device *dev)
-{
- struct primary_context *ctx = get_primary_context(dev);
-
- if (ctx->suspended)
- return;
-
- atomic_set(&ctx->wait_vsync_event, 1);
-
- if (!wait_event_timeout(ctx->wait_vsync_queue,
- !atomic_read(&ctx->wait_vsync_event),
- DRM_HZ/20))
- DRM_DEBUG_KMS("vblank wait timed out.\n");
-}
-
-static void primary_event_call_back_handle(struct rk_drm_display *drm_disp,int win_id,int event)
-{
- struct primary_context *ctx = get_primary_context(g_dev);
- struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
- struct rockchip_drm_manager *manager = subdrv->manager;
- struct drm_device *drm_dev = subdrv->drm_dev;
- switch(event){
- case RK_DRM_CALLBACK_VSYNC:
- /* check the crtc is detached already from encoder */
- if (manager->pipe < 0)
- return;
-
- drm_handle_vblank(drm_dev, manager->pipe);
- rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
- /* set wait vsync event to zero and wake up queue. */
- if (atomic_read(&ctx->wait_vsync_event)) {
- atomic_set(&ctx->wait_vsync_event, 0);
- DRM_WAKEUP(&ctx->wait_vsync_queue);
- }
- break;
- default:
- printk(KERN_ERR"-->%s unhandle event %d\n",__func__,event);
- break;
- }
-}
-static struct rockchip_drm_manager_ops primary_manager_ops = {
- .dpms = primary_dpms,
- .apply = primary_apply,
- .commit = primary_commit,
- .enable_vblank = primary_enable_vblank,
- .disable_vblank = primary_disable_vblank,
- .wait_for_vblank = primary_wait_for_vblank,
-};
-
-static void primary_win_mode_set(struct device *dev,
- struct rockchip_drm_overlay *overlay)
-{
- struct primary_context *ctx = get_primary_context(dev);
- struct primary_win_data *win_data;
- int win;
- unsigned long offset;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!overlay) {
- dev_err(dev, "overlay is NULL\n");
- return;
- }
-
- win = overlay->zpos;
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- offset = overlay->fb_x * (overlay->bpp >> 3);
- offset += overlay->fb_y * overlay->pitch;
-
-// printk("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
-// printk("crtc_x=%d crtc_y=%d crtc_width=%d crtc_height=%d\n",overlay->crtc_x,overlay->crtc_y,overlay->crtc_width,overlay->crtc_height);
-// printk("fb_width=%d fb_height=%d dma_addr=%x offset=%x\n",overlay->fb_width,overlay->fb_height,overlay->dma_addr[0],offset);
-
- win_data = &ctx->win_data[win];
-
- win_data->offset_x = overlay->crtc_x;
- win_data->offset_y = overlay->crtc_y;
- win_data->ovl_width = overlay->crtc_width;
- win_data->ovl_height = overlay->crtc_height;
- win_data->fb_width = overlay->fb_width;
- win_data->fb_height = overlay->fb_height;
- win_data->dma_addr = overlay->dma_addr[0] + offset;
- win_data->bpp = overlay->bpp;
- win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
- (overlay->bpp >> 3);
- win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
-
-}
-
-static void primary_win_set_pixfmt(struct device *dev, unsigned int win)
-{
- struct primary_context *ctx = get_primary_context(dev);
- struct primary_win_data *win_data = &ctx->win_data[win];
-}
-
-static void primary_win_set_colkey(struct device *dev, unsigned int win)
-{
-// struct primary_context *ctx = get_primary_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
-}
-#if 0
-static ktime_t win_start;
-static ktime_t win_end;
-static ktime_t win_start1;
-static ktime_t win_end1;
-#endif
-static void primary_win_commit(struct device *dev, int zpos)
-{
- struct primary_context *ctx = get_primary_context(dev);
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- struct rk_win_data *rk_win = NULL;
- struct primary_win_data *win_data;
- int win = zpos;
- unsigned long val, size;
- u32 xpos, ypos;
-
-// printk(KERN_ERR"%s %d\n", __func__,__LINE__);
-
- if (ctx->suspended)
- return;
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-#if 0
- if(win == 0){
- win_start = ktime_get();
- win_start = ktime_sub(win_start, win_end);
- printk("user flip buffer time %dus\n", (int)ktime_to_us(win_start));
- // win_start = ktime_get();
- }
-#endif
- rk_win = &drm_disp->win[win];
- win_data = &ctx->win_data[win];
- switch(win_data->bpp){
- case 32:
- rk_win->format = ARGB888;
- break;
- case 24:
- rk_win->format = RGB888;
- break;
- case 16:
- rk_win->format = RGB565;
- break;
- default:
- printk("not support format %d\n",win_data->bpp);
- break;
- }
-
- rk_win->xpos = win_data->offset_x;
- rk_win->ypos = win_data->offset_y;
- rk_win->xact = win_data->ovl_width;
- rk_win->yact = win_data->ovl_height;
- rk_win->xsize = win_data->ovl_width;
- rk_win->ysize = win_data->ovl_height;
- rk_win->xvir = win_data->fb_width;
- rk_win->yrgb_addr = win_data->dma_addr;
- rk_win->enabled = true;
-
- rk_drm_disp_handle(drm_disp,1<<win,RK_DRM_WIN_COMMIT | RK_DRM_DISPLAY_COMMIT);
-
- win_data->enabled = true;
-#if 0
- if(win ==0){
- // win_end = ktime_get();
- // win_end = ktime_sub(win_end, win_start);
- // printk("flip buffer time %dus\n", (int)ktime_to_us(win_end));
- win_end = ktime_get();
- }
-#endif
-
-}
-
-static void primary_win_disable(struct device *dev, int zpos)
-{
- struct primary_context *ctx = get_primary_context(dev);
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- struct primary_win_data *win_data;
- int win = zpos;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- win_data = &ctx->win_data[win];
-
- if (ctx->suspended) {
- /* do not resume this window*/
- win_data->resume = false;
- return;
- }
- drm_disp->win[win].enabled = false;
- rk_drm_disp_handle(drm_disp,1<<win,RK_DRM_WIN_COMMIT | RK_DRM_DISPLAY_COMMIT);
-
- win_data->enabled = false;
-}
-
-static struct rockchip_drm_overlay_ops primary_overlay_ops = {
- .mode_set = primary_win_mode_set,
- .commit = primary_win_commit,
- .disable = primary_win_disable,
-};
-
-static struct rockchip_drm_manager primary_manager = {
- .pipe = -1,
- .ops = &primary_manager_ops,
- .overlay_ops = &primary_overlay_ops,
- .display_ops = &primary_display_ops,
-};
-#if 0
-static irqreturn_t primary_irq_handler(int irq, void *dev_id)
-{
- struct primary_context *ctx = (struct primary_context *)dev_id;
- struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
- struct drm_device *drm_dev = subdrv->drm_dev;
- struct rockchip_drm_manager *manager = subdrv->manager;
- u32 intr0_reg;
-
-
-
- /* check the crtc is detached already from encoder */
- if (manager->pipe < 0)
- goto out;
-
- drm_handle_vblank(drm_dev, manager->pipe);
- rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
-
- /* set wait vsync event to zero and wake up queue. */
- if (atomic_read(&ctx->wait_vsync_event)) {
- atomic_set(&ctx->wait_vsync_event, 0);
- DRM_WAKEUP(&ctx->wait_vsync_queue);
- }
-out:
- return IRQ_HANDLED;
-}
-#endif
-static int primary_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * enable drm irq mode.
- * - with irq_enabled = 1, we can use the vblank feature.
- *
- * P.S. note that we wouldn't use drm irq handler but
- * just specific driver own one instead because
- * drm framework supports only one irq handler.
- */
- drm_dev->irq_enabled = 1;
-
- /*
- * with vblank_disable_allowed = 1, vblank interrupt will be disabled
- * by drm timer once a current process gives up ownership of
- * vblank event.(after drm_vblank_put function is called)
- */
- drm_dev->vblank_disable_allowed = 1;
-
- /* attach this sub driver to iommu mapping if supported. */
- if (is_drm_iommu_supported(drm_dev))
- drm_iommu_attach_device(drm_dev, dev);
-
- return 0;
-}
-
-static void primary_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* detach this sub driver from iommu mapping if supported. */
- if (is_drm_iommu_supported(drm_dev))
- drm_iommu_detach_device(drm_dev, dev);
-}
-
-
-static void primary_clear_win(struct primary_context *ctx, int win)
-{
- u32 val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
-}
-
-
-static void primary_window_suspend(struct device *dev)
-{
- struct primary_win_data *win_data = NULL;
- struct primary_context *ctx = get_primary_context(dev);
- int i;
-
- for (i = 0; i < WINDOWS_NR; i++) {
- win_data = &ctx->win_data[i];
- win_data->resume = win_data->enabled;
- primary_win_disable(dev, i);
- }
- primary_wait_for_vblank(dev);
-}
-
-static void primary_window_resume(struct device *dev)
-{
- struct primary_context *ctx = get_primary_context(dev);
- struct primary_win_data *win_data;
- int i;
-
- for (i = 0; i < WINDOWS_NR; i++) {
- win_data = &ctx->win_data[i];
- win_data->enabled = win_data->resume;
- win_data->resume = false;
- }
-}
-
-static int primary_activate(struct primary_context *ctx, bool enable)
-{
- struct device *dev = ctx->subdrv.dev;
- struct rk_drm_display *drm_disp = ctx->drm_disp;
- if (enable) {
- int ret;
-
- ctx->suspended = false;
-
- drm_disp->enable = true;
-
- rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_BLANK);
-
- /* if vblank was enabled status, enable it again. */
- if (ctx->vblank_en)
- primary_enable_vblank(dev);
-
- primary_window_resume(dev);
- } else {
- primary_window_suspend(dev);
-
- drm_disp->enable = false;
-
- rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_BLANK);
-
- ctx->suspended = true;
- }
-
- return 0;
-}
-
-static int primary_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct primary_context *ctx;
- struct rockchip_drm_subdrv *subdrv;
- struct rockchip_drm_panel_info *panel;
- struct rk_drm_display *drm_display = NULL;
- struct fb_modelist *modelist;
- struct fb_videomode *mode;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- g_dev = dev;
- ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
-
- panel = devm_kzalloc(dev, sizeof(struct rockchip_drm_panel_info), GFP_KERNEL);
- ctx->panel = panel;
-
- drm_display = rk_drm_get_diplay(RK_DRM_PRIMARY_SCREEN);
- ctx->drm_disp = drm_display;
- ctx->default_win = 0;
- modelist = list_first_entry(drm_display->modelist, struct fb_modelist, list);
- mode = &modelist->mode;
- memcpy(&panel->timing,mode,sizeof(struct fb_videomode));
-
- drm_display->event_call_back = primary_event_call_back_handle;
-
- DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
- atomic_set(&ctx->wait_vsync_event, 0);
-
- subdrv = &ctx->subdrv;
-
- subdrv->dev = dev;
- subdrv->manager = &primary_manager;
- subdrv->probe = primary_subdrv_probe;
- subdrv->remove = primary_subdrv_remove;
-
- mutex_init(&ctx->lock);
-
- platform_set_drvdata(pdev, ctx);
-
- pm_runtime_enable(dev);
- pm_runtime_get_sync(dev);
-
- //primary_commit(dev);
- primary_activate(ctx, true);
-
- rockchip_drm_subdrv_register(subdrv);
-
- return 0;
-}
-
-static int primary_remove(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct primary_context *ctx = platform_get_drvdata(pdev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- rockchip_drm_subdrv_unregister(&ctx->subdrv);
-
- if (ctx->suspended)
- goto out;
-
- pm_runtime_set_suspended(dev);
- pm_runtime_put_sync(dev);
-
-out:
- pm_runtime_disable(dev);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int primary_suspend(struct device *dev)
-{
- struct primary_context *ctx = get_primary_context(dev);
-
- /*
- * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
- * called here, an error would be returned by that interface
- * because the usage_count of pm runtime is more than 1.
- */
- if (!pm_runtime_suspended(dev))
- return primary_activate(ctx, false);
-
- return 0;
-}
-
-static int primary_resume(struct device *dev)
-{
- struct primary_context *ctx = get_primary_context(dev);
-
- /*
- * if entered to sleep when lcd panel was on, the usage_count
- * of pm runtime would still be 1 so in this case, fimd driver
- * should be on directly not drawing on pm runtime interface.
- */
- if (!pm_runtime_suspended(dev)) {
- int ret;
-
- ret = primary_activate(ctx, true);
- if (ret < 0)
- return ret;
-
- /*
- * in case of dpms on(standby), primary_apply function will
- * be called by encoder's dpms callback to update fimd's
- * registers but in case of sleep wakeup, it's not.
- * so primary_apply function should be called at here.
- */
- primary_apply(dev);
- }
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int primary_runtime_suspend(struct device *dev)
-{
- struct primary_context *ctx = get_primary_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return primary_activate(ctx, false);
-}
-
-static int primary_runtime_resume(struct device *dev)
-{
- struct primary_context *ctx = get_primary_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return primary_activate(ctx, true);
-}
-#endif
-
-static const struct dev_pm_ops primary_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(primary_suspend, primary_resume)
- SET_RUNTIME_PM_OPS(primary_runtime_suspend, primary_runtime_resume, NULL)
-};
-
-struct platform_driver primary_platform_driver = {
- .probe = primary_probe,
- .remove = primary_remove,
- .driver = {
- .owner = THIS_MODULE,
- .name = "primary-display",
- .pm = &primary_pm_ops,
- },
-};
+++ /dev/null
-#include "../../../video/rockchip/rk_drm_fb.h"
-#define WINDOWS_NR 4
-
-#define get_primary_context(dev) platform_get_drvdata(to_platform_device(dev))
-
-struct primary_win_data {
- unsigned int offset_x;
- unsigned int offset_y;
- unsigned int ovl_width;
- unsigned int ovl_height;
- unsigned int fb_width;
- unsigned int fb_height;
- unsigned int bpp;
- dma_addr_t dma_addr;
- unsigned int buf_offsize;
- unsigned int line_size; /* bytes */
- bool enabled;
- bool resume;
-};
-
-struct primary_context {
- struct rockchip_drm_subdrv subdrv;
- int vblank_en;
- struct drm_crtc *crtc;
- struct rk_drm_display *drm_disp;
- struct primary_win_data win_data[WINDOWS_NR];
- unsigned int default_win;
- bool suspended;
- struct mutex lock;
- wait_queue_head_t wait_vsync_queue;
- atomic_t wait_vsync_event;
-
- struct rockchip_drm_panel_info *panel;
-};