/*
* Copyright (C) 2012 Avionic Design GmbH
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/clk/tegra.h>
#include "host1x_client.h"
#include "dc.h"
#include "drm.h"
#include "gem.h"
struct tegra_plane {
struct drm_plane base;
unsigned int index;
};
static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
{
return container_of(plane, struct tegra_plane, base);
}
static int tegra_plane_update(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 tegra_plane *p = to_tegra_plane(plane);
struct tegra_dc *dc = to_tegra_dc(crtc);
struct tegra_dc_window window;
unsigned int i;
memset(&window, 0, sizeof(window));
window.src.x = src_x >> 16;
window.src.y = src_y >> 16;
window.src.w = src_w >> 16;
window.src.h = src_h >> 16;
window.dst.x = crtc_x;
window.dst.y = crtc_y;
window.dst.w = crtc_w;
window.dst.h = crtc_h;
window.format = tegra_dc_format(fb->pixel_format);
window.bits_per_pixel = fb->bits_per_pixel;
for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
window.base[i] = bo->paddr + fb->offsets[i];
/*
* Tegra doesn't support different strides for U and V planes
* so we display a warning if the user tries to display a
* framebuffer with such a configuration.
*/
if (i >= 2) {
if (fb->pitches[i] != window.stride[1])
DRM_ERROR("unsupported UV-plane configuration\n");
} else {
window.stride[i] = fb->pitches[i];
}
}
return tegra_dc_setup_window(dc, p->index, &window);
}
static int tegra_plane_disable(struct drm_plane *plane)
{
struct tegra_dc *dc = to_tegra_dc(plane->crtc);
struct tegra_plane *p = to_tegra_plane(plane);
unsigned long value;
if (!plane->crtc)
return 0;
value = WINDOW_A_SELECT << p->index;
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);