mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-16 04:04:06 +00:00
drm-misc-next for v5.15:
UAPI Changes: Cross-subsystem Changes: - Add lockdep_assert(once) helpers. Core Changes: - Add lockdep assert to drm_is_current_master_locked. - Fix typos in dma-buf documentation. - Mark drm irq midlayer as legacy only. - Fix GPF in udmabuf_create. - Rename member to correct value in drm_edid.h Driver Changes: - Build fix to make nouveau build with NOUVEAU_BACKLIGHT. - Add MI101AIT-ICP1, LTTD800480070-L6WWH-RT panels. - Assorted fixes to bridge/it66121, anx7625. - Add custom crtc_state to simple helpers, and use it to convert pll handling in mgag200 to atomic. - Convert drivers to use offset-adjusted framebuffer bo mappings. - Assorted small fixes and fix for a use-after-free in vmwgfx. - Convert remaining callers of non-legacy drivers to use linux irqs directly. - Small cleanup in ingenic. - Small fixes to virtio and ti-sn65dsi86. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAmEVd7cACgkQ/lWMcqZw E8Pw4hAApFWMPThb1OGxAsozhfOAc+Nhd/XjClWrEeu+auowge0OJzjUTOpUci7o NrL5GWLPDoIXm5/8eLm6B9k+hPmsuLQUgriMMpPyulvgckSYiLKzFEygbKtilfsJ k+ucLYlZ93ADLIcUIaode5eeWIbtsiuXNdfpH91uLKT2Lo1k4azJTfLJl0t1TB78 uAumaeLXirmqfyN8U/zgPSmaNyTgBlMjMrJG/0+NGaoiq3sKtC/vCU/4r2aEcsMd ZrYbAJph5ND/u449P4vk2mDNmpz6GE1i8y1zeq7OWq+EOFHaUv0M2v1ZGTl9NSCw CascPEb+Hzt4eMFEvpVn9Vz/p7NpVeT78733YkF6jO898pruDbJFz/1PFLUcWp5S jssvgYyhqTrLTCabg8OMrkww8S5on+qcRPVjrpaND2QJUrF58acrEQVCJmCf/XIg G2XXotZxv96upWj1n/bZz/KcNN7xc+J6z9SEZml/elz5er9msbL8OFEq9bxWxfKL xjDY0CwvRtkwnxkin6UpZHYlGGciY1j3pCMHiRpQNiHDQOfNE2pFbKHN0lWE7jiS wQaSMhxC8cjM1TpfHCeHmM522QS6oqJbPev9Z+2twO8KtfetbbBE3xe+Rm/Rf7eM vPRvHavWaRDlkq742qZqsiqP0aiqgr04i73Kw5mGLOCT/42uCuU= =G09r -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2021-08-12' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v5.15: UAPI Changes: Cross-subsystem Changes: - Add lockdep_assert(once) helpers. Core Changes: - Add lockdep assert to drm_is_current_master_locked. - Fix typos in dma-buf documentation. - Mark drm irq midlayer as legacy only. - Fix GPF in udmabuf_create. - Rename member to correct value in drm_edid.h Driver Changes: - Build fix to make nouveau build with NOUVEAU_BACKLIGHT. - Add MI101AIT-ICP1, LTTD800480070-L6WWH-RT panels. - Assorted fixes to bridge/it66121, anx7625. - Add custom crtc_state to simple helpers, and use it to convert pll handling in mgag200 to atomic. - Convert drivers to use offset-adjusted framebuffer bo mappings. - Assorted small fixes and fix for a use-after-free in vmwgfx. - Convert remaining callers of non-legacy drivers to use linux irqs directly. - Small cleanup in ingenic. - Small fixes to virtio and ti-sn65dsi86. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/1cf2d7fc-402d-1852-574a-21cbbd2eaebf@linux.intel.com
This commit is contained in:
commit
2819cf0e7d
91 changed files with 2000 additions and 1363 deletions
|
@ -227,8 +227,8 @@ static long udmabuf_create(struct miscdevice *device,
|
|||
if (!hpage) {
|
||||
hpage = find_get_page_flags(mapping, pgoff,
|
||||
FGP_ACCESSED);
|
||||
if (IS_ERR(hpage)) {
|
||||
ret = PTR_ERR(hpage);
|
||||
if (!hpage) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1786,7 +1786,6 @@ static const struct drm_driver amdgpu_kms_driver = {
|
|||
.open = amdgpu_driver_open_kms,
|
||||
.postclose = amdgpu_driver_postclose_kms,
|
||||
.lastclose = amdgpu_driver_lastclose_kms,
|
||||
.irq_handler = amdgpu_irq_handler,
|
||||
.ioctls = amdgpu_ioctls_kms,
|
||||
.num_ioctls = ARRAY_SIZE(amdgpu_ioctls_kms),
|
||||
.dumb_create = amdgpu_mode_dumb_create,
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include <linux/pci.h>
|
||||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
|
@ -184,7 +183,7 @@ void amdgpu_irq_disable_all(struct amdgpu_device *adev)
|
|||
* Returns:
|
||||
* result of handling the IRQ, as defined by &irqreturn_t
|
||||
*/
|
||||
irqreturn_t amdgpu_irq_handler(int irq, void *arg)
|
||||
static irqreturn_t amdgpu_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
|
@ -307,6 +306,7 @@ static void amdgpu_restore_msix(struct amdgpu_device *adev)
|
|||
int amdgpu_irq_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r = 0;
|
||||
unsigned int irq;
|
||||
|
||||
spin_lock_init(&adev->irq.lock);
|
||||
|
||||
|
@ -349,15 +349,22 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
|||
INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2);
|
||||
INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft);
|
||||
|
||||
adev->irq.installed = true;
|
||||
/* Use vector 0 for MSI-X */
|
||||
r = drm_irq_install(adev_to_drm(adev), pci_irq_vector(adev->pdev, 0));
|
||||
/* Use vector 0 for MSI-X. */
|
||||
r = pci_irq_vector(adev->pdev, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
irq = r;
|
||||
|
||||
/* PCI devices require shared interrupts. */
|
||||
r = request_irq(irq, amdgpu_irq_handler, IRQF_SHARED, adev_to_drm(adev)->driver->name,
|
||||
adev_to_drm(adev));
|
||||
if (r) {
|
||||
adev->irq.installed = false;
|
||||
if (!amdgpu_device_has_dc_support(adev))
|
||||
flush_work(&adev->hotplug_work);
|
||||
return r;
|
||||
}
|
||||
adev->irq.installed = true;
|
||||
adev->irq.irq = irq;
|
||||
adev_to_drm(adev)->max_vblank_count = 0x00ffffff;
|
||||
|
||||
DRM_DEBUG("amdgpu: irq initialized.\n");
|
||||
|
@ -368,7 +375,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
|||
void amdgpu_irq_fini_hw(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->irq.installed) {
|
||||
drm_irq_uninstall(&adev->ddev);
|
||||
free_irq(adev->irq.irq, adev_to_drm(adev));
|
||||
adev->irq.installed = false;
|
||||
if (adev->irq.msi_enabled)
|
||||
pci_free_irq_vectors(adev->pdev);
|
||||
|
|
|
@ -80,6 +80,7 @@ struct amdgpu_irq_src_funcs {
|
|||
|
||||
struct amdgpu_irq {
|
||||
bool installed;
|
||||
unsigned int irq;
|
||||
spinlock_t lock;
|
||||
/* interrupt sources */
|
||||
struct amdgpu_irq_client client[AMDGPU_IRQ_CLIENTID_MAX];
|
||||
|
@ -100,7 +101,6 @@ struct amdgpu_irq {
|
|||
};
|
||||
|
||||
void amdgpu_irq_disable_all(struct amdgpu_device *adev);
|
||||
irqreturn_t amdgpu_irq_handler(int irq, void *arg);
|
||||
|
||||
int amdgpu_irq_init(struct amdgpu_device *adev);
|
||||
void amdgpu_irq_fini_sw(struct amdgpu_device *adev);
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
@ -38,6 +37,94 @@
|
|||
#include "hdlcd_drv.h"
|
||||
#include "hdlcd_regs.h"
|
||||
|
||||
static irqreturn_t hdlcd_irq(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *drm = arg;
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
unsigned long irq_status;
|
||||
|
||||
irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
if (irq_status & HDLCD_INTERRUPT_UNDERRUN)
|
||||
atomic_inc(&hdlcd->buffer_underrun_count);
|
||||
|
||||
if (irq_status & HDLCD_INTERRUPT_DMA_END)
|
||||
atomic_inc(&hdlcd->dma_end_count);
|
||||
|
||||
if (irq_status & HDLCD_INTERRUPT_BUS_ERROR)
|
||||
atomic_inc(&hdlcd->bus_error_count);
|
||||
|
||||
if (irq_status & HDLCD_INTERRUPT_VSYNC)
|
||||
atomic_inc(&hdlcd->vsync_count);
|
||||
|
||||
#endif
|
||||
if (irq_status & HDLCD_INTERRUPT_VSYNC)
|
||||
drm_crtc_handle_vblank(&hdlcd->crtc);
|
||||
|
||||
/* acknowledge interrupt(s) */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void hdlcd_irq_preinstall(struct drm_device *drm)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
/* Ensure interrupts are disabled */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0);
|
||||
}
|
||||
|
||||
static void hdlcd_irq_postinstall(struct drm_device *drm)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
|
||||
|
||||
/* enable debug interrupts */
|
||||
irq_mask |= HDLCD_DEBUG_INT_MASK;
|
||||
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int hdlcd_irq_install(struct drm_device *drm, int irq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (irq == IRQ_NOTCONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
hdlcd_irq_preinstall(drm);
|
||||
|
||||
ret = request_irq(irq, hdlcd_irq, 0, drm->driver->name, drm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdlcd_irq_postinstall(drm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hdlcd_irq_uninstall(struct drm_device *drm)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
/* disable all the interrupts that we might have enabled */
|
||||
unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
/* disable debug interrupts */
|
||||
irq_mask &= ~HDLCD_DEBUG_INT_MASK;
|
||||
#endif
|
||||
|
||||
/* disable vsync interrupts */
|
||||
irq_mask &= ~HDLCD_INTERRUPT_VSYNC;
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
|
||||
|
||||
free_irq(hdlcd->irq, drm);
|
||||
}
|
||||
|
||||
static int hdlcd_load(struct drm_device *drm, unsigned long flags)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
|
@ -90,7 +177,12 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
|
|||
goto setup_fail;
|
||||
}
|
||||
|
||||
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
goto irq_fail;
|
||||
hdlcd->irq = ret;
|
||||
|
||||
ret = hdlcd_irq_install(drm, hdlcd->irq);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to install IRQ handler\n");
|
||||
goto irq_fail;
|
||||
|
@ -122,76 +214,6 @@ static void hdlcd_setup_mode_config(struct drm_device *drm)
|
|||
drm->mode_config.funcs = &hdlcd_mode_config_funcs;
|
||||
}
|
||||
|
||||
static irqreturn_t hdlcd_irq(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *drm = arg;
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
unsigned long irq_status;
|
||||
|
||||
irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
if (irq_status & HDLCD_INTERRUPT_UNDERRUN)
|
||||
atomic_inc(&hdlcd->buffer_underrun_count);
|
||||
|
||||
if (irq_status & HDLCD_INTERRUPT_DMA_END)
|
||||
atomic_inc(&hdlcd->dma_end_count);
|
||||
|
||||
if (irq_status & HDLCD_INTERRUPT_BUS_ERROR)
|
||||
atomic_inc(&hdlcd->bus_error_count);
|
||||
|
||||
if (irq_status & HDLCD_INTERRUPT_VSYNC)
|
||||
atomic_inc(&hdlcd->vsync_count);
|
||||
|
||||
#endif
|
||||
if (irq_status & HDLCD_INTERRUPT_VSYNC)
|
||||
drm_crtc_handle_vblank(&hdlcd->crtc);
|
||||
|
||||
/* acknowledge interrupt(s) */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void hdlcd_irq_preinstall(struct drm_device *drm)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
/* Ensure interrupts are disabled */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0);
|
||||
}
|
||||
|
||||
static int hdlcd_irq_postinstall(struct drm_device *drm)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
|
||||
|
||||
/* enable debug interrupts */
|
||||
irq_mask |= HDLCD_DEBUG_INT_MASK;
|
||||
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hdlcd_irq_uninstall(struct drm_device *drm)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
/* disable all the interrupts that we might have enabled */
|
||||
unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
/* disable debug interrupts */
|
||||
irq_mask &= ~HDLCD_DEBUG_INT_MASK;
|
||||
#endif
|
||||
|
||||
/* disable vsync interrupts */
|
||||
irq_mask &= ~HDLCD_INTERRUPT_VSYNC;
|
||||
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static int hdlcd_show_underrun_count(struct seq_file *m, void *arg)
|
||||
{
|
||||
|
@ -236,10 +258,6 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
|
|||
|
||||
static const struct drm_driver hdlcd_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.irq_handler = hdlcd_irq,
|
||||
.irq_preinstall = hdlcd_irq_preinstall,
|
||||
.irq_postinstall = hdlcd_irq_postinstall,
|
||||
.irq_uninstall = hdlcd_irq_uninstall,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.debugfs_init = hdlcd_debugfs_init,
|
||||
|
@ -316,7 +334,7 @@ err_pm_active:
|
|||
err_unload:
|
||||
of_node_put(hdlcd->crtc.port);
|
||||
hdlcd->crtc.port = NULL;
|
||||
drm_irq_uninstall(drm);
|
||||
hdlcd_irq_uninstall(drm);
|
||||
of_reserved_mem_device_release(drm->dev);
|
||||
err_free:
|
||||
drm_mode_config_cleanup(drm);
|
||||
|
@ -338,7 +356,7 @@ static void hdlcd_drm_unbind(struct device *dev)
|
|||
hdlcd->crtc.port = NULL;
|
||||
pm_runtime_get_sync(dev);
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
drm_irq_uninstall(drm);
|
||||
hdlcd_irq_uninstall(drm);
|
||||
pm_runtime_put(dev);
|
||||
if (pm_runtime_enabled(dev))
|
||||
pm_runtime_disable(dev);
|
||||
|
|
|
@ -11,6 +11,7 @@ struct hdlcd_drm_private {
|
|||
struct clk *clk;
|
||||
struct drm_crtc crtc;
|
||||
struct drm_plane *plane;
|
||||
unsigned int irq;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
atomic_t buffer_underrun_count;
|
||||
atomic_t bus_error_count;
|
||||
|
|
|
@ -808,7 +808,7 @@ ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
|
|||
ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].map;
|
||||
u64 dst_off =
|
||||
ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].off;
|
||||
struct dma_buf_map src_map = shadow_plane_state->map[0];
|
||||
struct dma_buf_map src_map = shadow_plane_state->data[0];
|
||||
unsigned int offset_x, offset_y;
|
||||
u16 x, y;
|
||||
u8 x_offset, y_offset;
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
|
@ -557,6 +556,51 @@ static irqreturn_t atmel_hlcdc_dc_irq_handler(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
struct atmel_hlcdc_dc *dc = dev->dev_private;
|
||||
unsigned int cfg = 0;
|
||||
int i;
|
||||
|
||||
/* Enable interrupts on activated layers */
|
||||
for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
|
||||
if (dc->layers[i])
|
||||
cfg |= ATMEL_HLCDC_LAYER_STATUS(i);
|
||||
}
|
||||
|
||||
regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, cfg);
|
||||
}
|
||||
|
||||
static void atmel_hlcdc_dc_irq_disable(struct drm_device *dev)
|
||||
{
|
||||
struct atmel_hlcdc_dc *dc = dev->dev_private;
|
||||
unsigned int isr;
|
||||
|
||||
regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IDR, 0xffffffff);
|
||||
regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr);
|
||||
}
|
||||
|
||||
static int atmel_hlcdc_dc_irq_install(struct drm_device *dev, unsigned int irq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
atmel_hlcdc_dc_irq_disable(dev);
|
||||
|
||||
ret = devm_request_irq(dev->dev, irq, atmel_hlcdc_dc_irq_handler, 0,
|
||||
dev->driver->name, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
atmel_hlcdc_dc_irq_postinstall(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
atmel_hlcdc_dc_irq_disable(dev);
|
||||
}
|
||||
|
||||
static const struct drm_mode_config_funcs mode_config_funcs = {
|
||||
.fb_create = drm_gem_fb_create,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
|
@ -647,7 +691,7 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
|
|||
drm_mode_config_reset(dev);
|
||||
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
ret = drm_irq_install(dev, dc->hlcdc->irq);
|
||||
ret = atmel_hlcdc_dc_irq_install(dev, dc->hlcdc->irq);
|
||||
pm_runtime_put_sync(dev->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to install IRQ handler\n");
|
||||
|
@ -676,7 +720,7 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
|
|||
drm_mode_config_cleanup(dev);
|
||||
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
drm_irq_uninstall(dev);
|
||||
atmel_hlcdc_dc_irq_uninstall(dev);
|
||||
pm_runtime_put_sync(dev->dev);
|
||||
|
||||
dev->dev_private = NULL;
|
||||
|
@ -685,40 +729,10 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
|
|||
clk_disable_unprepare(dc->hlcdc->periph_clk);
|
||||
}
|
||||
|
||||
static int atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
struct atmel_hlcdc_dc *dc = dev->dev_private;
|
||||
unsigned int cfg = 0;
|
||||
int i;
|
||||
|
||||
/* Enable interrupts on activated layers */
|
||||
for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
|
||||
if (dc->layers[i])
|
||||
cfg |= ATMEL_HLCDC_LAYER_STATUS(i);
|
||||
}
|
||||
|
||||
regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
struct atmel_hlcdc_dc *dc = dev->dev_private;
|
||||
unsigned int isr;
|
||||
|
||||
regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IDR, 0xffffffff);
|
||||
regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr);
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(fops);
|
||||
|
||||
static const struct drm_driver atmel_hlcdc_dc_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.irq_handler = atmel_hlcdc_dc_irq_handler,
|
||||
.irq_preinstall = atmel_hlcdc_dc_irq_uninstall,
|
||||
.irq_postinstall = atmel_hlcdc_dc_irq_postinstall,
|
||||
.irq_uninstall = atmel_hlcdc_dc_irq_uninstall,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
.fops = &fops,
|
||||
.name = "atmel-hlcdc",
|
||||
|
|
|
@ -384,6 +384,25 @@ static int anx7625_odfc_config(struct anx7625_data *ctx,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The MIPI source video data exist large variation (e.g. 59Hz ~ 61Hz),
|
||||
* anx7625 defined K ratio for matching MIPI input video clock and
|
||||
* DP output video clock. Increase K value can match bigger video data
|
||||
* variation. IVO panel has small variation than DP CTS spec, need
|
||||
* decrease the K value.
|
||||
*/
|
||||
static int anx7625_set_k_value(struct anx7625_data *ctx)
|
||||
{
|
||||
struct edid *edid = (struct edid *)ctx->slimport_edid_p.edid_raw_data;
|
||||
|
||||
if (edid->mfg_id[0] == IVO_MID0 && edid->mfg_id[1] == IVO_MID1)
|
||||
return anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
|
||||
MIPI_DIGITAL_ADJ_1, 0x3B);
|
||||
|
||||
return anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
|
||||
MIPI_DIGITAL_ADJ_1, 0x3D);
|
||||
}
|
||||
|
||||
static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
|
||||
{
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
@ -470,9 +489,8 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
|
|||
MIPI_PLL_N_NUM_15_8, (n >> 8) & 0xff);
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client, MIPI_PLL_N_NUM_7_0,
|
||||
(n & 0xff));
|
||||
/* Diff */
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
|
||||
MIPI_DIGITAL_ADJ_1, 0x3D);
|
||||
|
||||
anx7625_set_k_value(ctx);
|
||||
|
||||
ret |= anx7625_odfc_config(ctx, post_divider - 1);
|
||||
|
||||
|
|
|
@ -210,7 +210,9 @@
|
|||
#define MIPI_VIDEO_STABLE_CNT 0x0A
|
||||
|
||||
#define MIPI_LANE_CTRL_10 0x0F
|
||||
#define MIPI_DIGITAL_ADJ_1 0x1B
|
||||
#define MIPI_DIGITAL_ADJ_1 0x1B
|
||||
#define IVO_MID0 0x26
|
||||
#define IVO_MID1 0xCF
|
||||
|
||||
#define MIPI_PLL_M_NUM_23_16 0x1E
|
||||
#define MIPI_PLL_M_NUM_15_8 0x1F
|
||||
|
|
|
@ -536,6 +536,8 @@ static int it66121_bridge_attach(struct drm_bridge *bridge,
|
|||
return -EINVAL;
|
||||
|
||||
ret = drm_bridge_attach(bridge->encoder, ctx->next_bridge, bridge, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG,
|
||||
IT66121_CLK_BANK_PWROFF_RCLK, 0);
|
||||
|
|
|
@ -739,6 +739,9 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
|
|||
}
|
||||
pdata->dsi = dsi;
|
||||
|
||||
/* We never want the next bridge to *also* create a connector: */
|
||||
flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR;
|
||||
|
||||
/* Attach the next bridge */
|
||||
ret = drm_bridge_attach(bridge->encoder, pdata->next_bridge,
|
||||
&pdata->bridge, flags);
|
||||
|
|
|
@ -63,9 +63,9 @@
|
|||
|
||||
static bool drm_is_current_master_locked(struct drm_file *fpriv)
|
||||
{
|
||||
/* Either drm_device.master_mutex or drm_file.master_lookup_lock
|
||||
* should be held here.
|
||||
*/
|
||||
lockdep_assert_once(lockdep_is_held(&fpriv->master_lookup_lock) ||
|
||||
lockdep_is_held(&fpriv->minor->dev->master_mutex));
|
||||
|
||||
return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master;
|
||||
}
|
||||
|
||||
|
|
|
@ -339,7 +339,7 @@ int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *p
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return drm_gem_fb_vmap(fb, shadow_plane_state->map);
|
||||
return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_prepare_shadow_fb);
|
||||
|
||||
|
|
|
@ -315,19 +315,25 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty);
|
|||
* drm_gem_fb_vmap - maps all framebuffer BOs into kernel address space
|
||||
* @fb: the framebuffer
|
||||
* @map: returns the mapping's address for each BO
|
||||
* @data: returns the data address for each BO, can be NULL
|
||||
*
|
||||
* This function maps all buffer objects of the given framebuffer into
|
||||
* kernel address space and stores them in struct dma_buf_map. If the
|
||||
* mapping operation fails for one of the BOs, the function unmaps the
|
||||
* already established mappings automatically.
|
||||
*
|
||||
* Callers that want to access a BO's stored data should pass @data.
|
||||
* The argument returns the addresses of the data stored in each BO. This
|
||||
* is different from @map if the framebuffer's offsets field is non-zero.
|
||||
*
|
||||
* See drm_gem_fb_vunmap() for unmapping.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, or a negative errno code otherwise.
|
||||
*/
|
||||
int drm_gem_fb_vmap(struct drm_framebuffer *fb,
|
||||
struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES])
|
||||
struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES],
|
||||
struct dma_buf_map data[DRM_FORMAT_MAX_PLANES])
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
unsigned int i;
|
||||
|
@ -344,6 +350,15 @@ int drm_gem_fb_vmap(struct drm_framebuffer *fb,
|
|||
goto err_drm_gem_vunmap;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
for (i = 0; i < DRM_FORMAT_MAX_PLANES; ++i) {
|
||||
memcpy(&data[i], &map[i], sizeof(data[i]));
|
||||
if (dma_buf_map_is_null(&data[i]))
|
||||
continue;
|
||||
dma_buf_map_incr(&data[i], fb->offsets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_drm_gem_vunmap:
|
||||
|
|
|
@ -60,46 +60,14 @@
|
|||
#include <drm/drm.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_legacy.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
|
||||
/**
|
||||
* DOC: irq helpers
|
||||
*
|
||||
* The DRM core provides very simple support helpers to enable IRQ handling on a
|
||||
* device through the drm_irq_install() and drm_irq_uninstall() functions. This
|
||||
* only supports devices with a single interrupt on the main device stored in
|
||||
* &drm_device.dev and set as the device parameter in drm_dev_alloc().
|
||||
*
|
||||
* These IRQ helpers are strictly optional. Since these helpers don't automatically
|
||||
* clean up the requested interrupt like e.g. devm_request_irq() they're not really
|
||||
* recommended.
|
||||
*/
|
||||
|
||||
/**
|
||||
* drm_irq_install - install IRQ handler
|
||||
* @dev: DRM device
|
||||
* @irq: IRQ number to install the handler for
|
||||
*
|
||||
* Initializes the IRQ related data. Installs the handler, calling the driver
|
||||
* &drm_driver.irq_preinstall and &drm_driver.irq_postinstall functions before
|
||||
* and after the installation.
|
||||
*
|
||||
* This is the simplified helper interface provided for drivers with no special
|
||||
* needs.
|
||||
*
|
||||
* @irq must match the interrupt number that would be passed to request_irq(),
|
||||
* if called directly instead of using this helper function.
|
||||
*
|
||||
* &drm_driver.irq_handler is called to handle the registered interrupt.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_irq_install(struct drm_device *dev, int irq)
|
||||
#if IS_ENABLED(CONFIG_DRM_LEGACY)
|
||||
static int drm_legacy_irq_install(struct drm_device *dev, int irq)
|
||||
{
|
||||
int ret;
|
||||
unsigned long sh_flags = 0;
|
||||
|
@ -144,24 +112,8 @@ int drm_irq_install(struct drm_device *dev, int irq)
|
|||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_irq_install);
|
||||
|
||||
/**
|
||||
* drm_irq_uninstall - uninstall the IRQ handler
|
||||
* @dev: DRM device
|
||||
*
|
||||
* Calls the driver's &drm_driver.irq_uninstall function and unregisters the IRQ
|
||||
* handler. This should only be called by drivers which used drm_irq_install()
|
||||
* to set up their interrupt handler.
|
||||
*
|
||||
* Note that for kernel modesetting drivers it is a bug if this function fails.
|
||||
* The sanity checks are only to catch buggy user modesetting drivers which call
|
||||
* the same function through an ioctl.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_irq_uninstall(struct drm_device *dev)
|
||||
int drm_legacy_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
bool irq_enabled;
|
||||
|
@ -207,41 +159,8 @@ int drm_irq_uninstall(struct drm_device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_irq_uninstall);
|
||||
EXPORT_SYMBOL(drm_legacy_irq_uninstall);
|
||||
|
||||
static void devm_drm_irq_uninstall(void *data)
|
||||
{
|
||||
drm_irq_uninstall(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_drm_irq_install - install IRQ handler
|
||||
* @dev: DRM device
|
||||
* @irq: IRQ number to install the handler for
|
||||
*
|
||||
* devm_drm_irq_install is a help function of drm_irq_install.
|
||||
*
|
||||
* if the driver uses devm_drm_irq_install, there is no need
|
||||
* to call drm_irq_uninstall when the drm module get unloaded,
|
||||
* as this will done automagically.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success or a negative error code on failure.
|
||||
*/
|
||||
int devm_drm_irq_install(struct drm_device *dev, int irq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_irq_install(dev, irq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_add_action_or_reset(dev->dev,
|
||||
devm_drm_irq_uninstall, dev);
|
||||
}
|
||||
EXPORT_SYMBOL(devm_drm_irq_install);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_LEGACY)
|
||||
int drm_legacy_irq_control(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
|
@ -270,13 +189,13 @@ int drm_legacy_irq_control(struct drm_device *dev, void *data,
|
|||
ctl->irq != irq)
|
||||
return -EINVAL;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ret = drm_irq_install(dev, irq);
|
||||
ret = drm_legacy_irq_install(dev, irq);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return ret;
|
||||
case DRM_UNINST_HANDLER:
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ret = drm_irq_uninstall(dev);
|
||||
ret = drm_legacy_irq_uninstall(dev);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
|
@ -78,7 +77,7 @@ int drm_legacy_setup(struct drm_device * dev)
|
|||
void drm_legacy_dev_reinit(struct drm_device *dev)
|
||||
{
|
||||
if (dev->irq_enabled)
|
||||
drm_irq_uninstall(dev);
|
||||
drm_legacy_irq_uninstall(dev);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
|
|
|
@ -145,6 +145,39 @@ static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = {
|
|||
.atomic_disable = drm_simple_kms_crtc_disable,
|
||||
};
|
||||
|
||||
static void drm_simple_kms_crtc_reset(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_simple_display_pipe *pipe;
|
||||
|
||||
pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
|
||||
if (!pipe->funcs || !pipe->funcs->reset_crtc)
|
||||
return drm_atomic_helper_crtc_reset(crtc);
|
||||
|
||||
return pipe->funcs->reset_crtc(pipe);
|
||||
}
|
||||
|
||||
static struct drm_crtc_state *drm_simple_kms_crtc_duplicate_state(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_simple_display_pipe *pipe;
|
||||
|
||||
pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
|
||||
if (!pipe->funcs || !pipe->funcs->duplicate_crtc_state)
|
||||
return drm_atomic_helper_crtc_duplicate_state(crtc);
|
||||
|
||||
return pipe->funcs->duplicate_crtc_state(pipe);
|
||||
}
|
||||
|
||||
static void drm_simple_kms_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state)
|
||||
{
|
||||
struct drm_simple_display_pipe *pipe;
|
||||
|
||||
pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
|
||||
if (!pipe->funcs || !pipe->funcs->destroy_crtc_state)
|
||||
drm_atomic_helper_crtc_destroy_state(crtc, state);
|
||||
else
|
||||
pipe->funcs->destroy_crtc_state(pipe, state);
|
||||
}
|
||||
|
||||
static int drm_simple_kms_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_simple_display_pipe *pipe;
|
||||
|
@ -168,12 +201,12 @@ static void drm_simple_kms_crtc_disable_vblank(struct drm_crtc *crtc)
|
|||
}
|
||||
|
||||
static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = {
|
||||
.reset = drm_atomic_helper_crtc_reset,
|
||||
.reset = drm_simple_kms_crtc_reset,
|
||||
.destroy = drm_crtc_cleanup,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
|
||||
.atomic_duplicate_state = drm_simple_kms_crtc_duplicate_state,
|
||||
.atomic_destroy_state = drm_simple_kms_crtc_destroy_state,
|
||||
.enable_vblank = drm_simple_kms_crtc_enable_vblank,
|
||||
.disable_vblank = drm_simple_kms_crtc_disable_vblank,
|
||||
};
|
||||
|
|
|
@ -1739,10 +1739,10 @@ static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe,
|
|||
|
||||
static bool drm_wait_vblank_supported(struct drm_device *dev)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_DRM_LEGACY)) {
|
||||
if (unlikely(drm_core_check_feature(dev, DRIVER_LEGACY)))
|
||||
return dev->irq_enabled;
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_DRM_LEGACY)
|
||||
if (unlikely(drm_core_check_feature(dev, DRIVER_LEGACY)))
|
||||
return dev->irq_enabled;
|
||||
#endif
|
||||
return drm_dev_has_vblank(dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
@ -51,7 +50,7 @@ static const struct regmap_config fsl_dcu_regmap_config = {
|
|||
.volatile_reg = fsl_dcu_drm_is_volatile_reg,
|
||||
};
|
||||
|
||||
static void fsl_dcu_irq_uninstall(struct drm_device *dev)
|
||||
static void fsl_dcu_irq_reset(struct drm_device *dev)
|
||||
{
|
||||
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
|
||||
|
||||
|
@ -59,58 +58,6 @@ static void fsl_dcu_irq_uninstall(struct drm_device *dev)
|
|||
regmap_write(fsl_dev->regmap, DCU_INT_MASK, ~0);
|
||||
}
|
||||
|
||||
static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = fsl_dcu_drm_modeset_init(fsl_dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to initialize mode setting\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to initialize vblank\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = drm_irq_install(dev, fsl_dev->irq);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to install IRQ handler\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (legacyfb_depth != 16 && legacyfb_depth != 24 &&
|
||||
legacyfb_depth != 32) {
|
||||
dev_warn(dev->dev,
|
||||
"Invalid legacyfb_depth. Defaulting to 24bpp\n");
|
||||
legacyfb_depth = 24;
|
||||
}
|
||||
|
||||
return 0;
|
||||
done:
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
|
||||
drm_mode_config_cleanup(dev);
|
||||
drm_irq_uninstall(dev);
|
||||
dev->dev_private = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fsl_dcu_unload(struct drm_device *dev)
|
||||
{
|
||||
drm_atomic_helper_shutdown(dev);
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
|
||||
drm_mode_config_cleanup(dev);
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
dev->dev_private = NULL;
|
||||
}
|
||||
|
||||
static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = arg;
|
||||
|
@ -132,15 +79,82 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int fsl_dcu_irq_install(struct drm_device *dev, unsigned int irq)
|
||||
{
|
||||
if (irq == IRQ_NOTCONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
fsl_dcu_irq_reset(dev);
|
||||
|
||||
return request_irq(irq, fsl_dcu_drm_irq, 0, dev->driver->name, dev);
|
||||
}
|
||||
|
||||
static void fsl_dcu_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
|
||||
|
||||
fsl_dcu_irq_reset(dev);
|
||||
free_irq(fsl_dev->irq, dev);
|
||||
}
|
||||
|
||||
static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = fsl_dcu_drm_modeset_init(fsl_dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to initialize mode setting\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to initialize vblank\n");
|
||||
goto done_vblank;
|
||||
}
|
||||
|
||||
ret = fsl_dcu_irq_install(dev, fsl_dev->irq);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to install IRQ handler\n");
|
||||
goto done_irq;
|
||||
}
|
||||
|
||||
if (legacyfb_depth != 16 && legacyfb_depth != 24 &&
|
||||
legacyfb_depth != 32) {
|
||||
dev_warn(dev->dev,
|
||||
"Invalid legacyfb_depth. Defaulting to 24bpp\n");
|
||||
legacyfb_depth = 24;
|
||||
}
|
||||
|
||||
return 0;
|
||||
done_irq:
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
|
||||
drm_mode_config_cleanup(dev);
|
||||
done_vblank:
|
||||
dev->dev_private = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fsl_dcu_unload(struct drm_device *dev)
|
||||
{
|
||||
drm_atomic_helper_shutdown(dev);
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
|
||||
drm_mode_config_cleanup(dev);
|
||||
fsl_dcu_irq_uninstall(dev);
|
||||
|
||||
dev->dev_private = NULL;
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(fsl_dcu_drm_fops);
|
||||
|
||||
static const struct drm_driver fsl_dcu_drm_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.load = fsl_dcu_load,
|
||||
.unload = fsl_dcu_unload,
|
||||
.irq_handler = fsl_dcu_drm_irq,
|
||||
.irq_preinstall = fsl_dcu_irq_uninstall,
|
||||
.irq_uninstall = fsl_dcu_irq_uninstall,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
.fops = &fsl_dcu_drm_fops,
|
||||
.name = "fsl-dcu-drm",
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "psb_drv.h"
|
||||
#include "psb_reg.h"
|
||||
#include "psb_intel_reg.h"
|
||||
#include "psb_irq.h"
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_ioctl.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_pciids.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
|
@ -33,6 +32,7 @@
|
|||
#include "power.h"
|
||||
#include "psb_drv.h"
|
||||
#include "psb_intel_reg.h"
|
||||
#include "psb_irq.h"
|
||||
#include "psb_reg.h"
|
||||
|
||||
static const struct drm_driver driver;
|
||||
|
@ -380,7 +380,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
|
||||
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
|
||||
|
||||
drm_irq_install(dev, pdev->irq);
|
||||
psb_irq_install(dev, pdev->irq);
|
||||
|
||||
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
||||
|
||||
|
@ -515,10 +515,6 @@ static const struct drm_driver driver = {
|
|||
.lastclose = drm_fb_helper_lastclose,
|
||||
|
||||
.num_ioctls = ARRAY_SIZE(psb_ioctls),
|
||||
.irq_preinstall = psb_irq_preinstall,
|
||||
.irq_postinstall = psb_irq_postinstall,
|
||||
.irq_uninstall = psb_irq_uninstall,
|
||||
.irq_handler = psb_irq_handler,
|
||||
|
||||
.dumb_create = psb_gem_dumb_create,
|
||||
.ioctls = psb_ioctls,
|
||||
|
|
|
@ -624,11 +624,6 @@ static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
|
|||
}
|
||||
|
||||
/* psb_irq.c */
|
||||
extern irqreturn_t psb_irq_handler(int irq, void *arg);
|
||||
extern void psb_irq_preinstall(struct drm_device *dev);
|
||||
extern int psb_irq_postinstall(struct drm_device *dev);
|
||||
extern void psb_irq_uninstall(struct drm_device *dev);
|
||||
|
||||
extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
|
||||
extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
|
||||
extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "power.h"
|
||||
|
@ -222,7 +223,7 @@ static void psb_sgx_interrupt(struct drm_device *dev, u32 stat_1, u32 stat_2)
|
|||
PSB_RSGX32(PSB_CR_EVENT_HOST_CLEAR2);
|
||||
}
|
||||
|
||||
irqreturn_t psb_irq_handler(int irq, void *arg)
|
||||
static irqreturn_t psb_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = arg;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
|
@ -304,7 +305,7 @@ void psb_irq_preinstall(struct drm_device *dev)
|
|||
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
|
||||
}
|
||||
|
||||
int psb_irq_postinstall(struct drm_device *dev)
|
||||
void psb_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
|
@ -332,12 +333,31 @@ int psb_irq_postinstall(struct drm_device *dev)
|
|||
dev_priv->ops->hotplug_enable(dev, true);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
|
||||
}
|
||||
|
||||
int psb_irq_install(struct drm_device *dev, unsigned int irq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (irq == IRQ_NOTCONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
psb_irq_preinstall(dev);
|
||||
|
||||
/* PCI devices require shared interrupts. */
|
||||
ret = request_irq(irq, psb_irq_handler, IRQF_SHARED, dev->driver->name, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
psb_irq_postinstall(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void psb_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
||||
unsigned long irqflags;
|
||||
unsigned int i;
|
||||
|
||||
|
@ -366,6 +386,8 @@ void psb_irq_uninstall(struct drm_device *dev)
|
|||
/* This register is safe even if display island is off */
|
||||
PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
|
||||
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
|
||||
|
||||
free_irq(pdev->irq, dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -19,9 +19,9 @@ bool sysirq_init(struct drm_device *dev);
|
|||
void sysirq_uninit(struct drm_device *dev);
|
||||
|
||||
void psb_irq_preinstall(struct drm_device *dev);
|
||||
int psb_irq_postinstall(struct drm_device *dev);
|
||||
void psb_irq_postinstall(struct drm_device *dev);
|
||||
int psb_irq_install(struct drm_device *dev, unsigned int irq);
|
||||
void psb_irq_uninstall(struct drm_device *dev);
|
||||
irqreturn_t psb_irq_handler(int irq, void *arg);
|
||||
|
||||
int psb_enable_vblank(struct drm_crtc *crtc);
|
||||
void psb_disable_vblank(struct drm_crtc *crtc);
|
||||
|
|
|
@ -153,6 +153,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
|
|||
struct dma_buf_attachment *import_attach = fb->obj[0]->import_attach;
|
||||
u8 compression = gdrm->compression;
|
||||
struct dma_buf_map map[DRM_FORMAT_MAX_PLANES];
|
||||
struct dma_buf_map map_data[DRM_FORMAT_MAX_PLANES];
|
||||
void *vaddr, *buf;
|
||||
size_t pitch, len;
|
||||
int ret = 0;
|
||||
|
@ -162,11 +163,11 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
|
|||
if (len > gdrm->bulk_len)
|
||||
return -E2BIG;
|
||||
|
||||
ret = drm_gem_fb_vmap(fb, map);
|
||||
ret = drm_gem_fb_vmap(fb, map, map_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vaddr = map[0].vaddr + fb->offsets[0];
|
||||
vaddr = map_data[0].vaddr;
|
||||
|
||||
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
|
|
|
@ -105,7 +105,7 @@ static void hyperv_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||
crtc_state->mode.hdisplay,
|
||||
crtc_state->mode.vdisplay,
|
||||
plane_state->fb->pitches[0]);
|
||||
hyperv_blit_to_vram_fullscreen(plane_state->fb, &shadow_plane_state->map[0]);
|
||||
hyperv_blit_to_vram_fullscreen(plane_state->fb, &shadow_plane_state->data[0]);
|
||||
}
|
||||
|
||||
static int hyperv_pipe_check(struct drm_simple_display_pipe *pipe,
|
||||
|
@ -133,7 +133,7 @@ static void hyperv_pipe_update(struct drm_simple_display_pipe *pipe,
|
|||
struct drm_rect rect;
|
||||
|
||||
if (drm_atomic_helper_damage_merged(old_state, state, &rect)) {
|
||||
hyperv_blit_to_vram_rect(state->fb, &shadow_plane_state->map[0], &rect);
|
||||
hyperv_blit_to_vram_rect(state->fb, &shadow_plane_state->data[0], &rect);
|
||||
hyperv_update_dirt(hv->hdev, &rect);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_ioctl.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/i810_drm.h>
|
||||
|
||||
|
@ -209,7 +208,7 @@ static int i810_dma_cleanup(struct drm_device *dev)
|
|||
* is freed, it's too late.
|
||||
*/
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled)
|
||||
drm_irq_uninstall(dev);
|
||||
drm_legacy_irq_uninstall(dev);
|
||||
|
||||
if (dev->dev_private) {
|
||||
int i;
|
||||
|
|
|
@ -701,29 +701,6 @@ static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
|
|||
}
|
||||
}
|
||||
|
||||
static void ingenic_drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state)
|
||||
{
|
||||
/*
|
||||
* Just your regular drm_atomic_helper_commit_tail(), but only calls
|
||||
* drm_atomic_helper_wait_for_vblanks() if priv->no_vblank.
|
||||
*/
|
||||
struct drm_device *dev = old_state->dev;
|
||||
struct ingenic_drm *priv = drm_device_get_priv(dev);
|
||||
|
||||
drm_atomic_helper_commit_modeset_disables(dev, old_state);
|
||||
|
||||
drm_atomic_helper_commit_planes(dev, old_state, 0);
|
||||
|
||||
drm_atomic_helper_commit_modeset_enables(dev, old_state);
|
||||
|
||||
drm_atomic_helper_commit_hw_done(old_state);
|
||||
|
||||
if (!priv->no_vblank)
|
||||
drm_atomic_helper_wait_for_vblanks(dev, old_state);
|
||||
|
||||
drm_atomic_helper_cleanup_planes(dev, old_state);
|
||||
}
|
||||
|
||||
static irqreturn_t ingenic_drm_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct ingenic_drm *priv = drm_device_get_priv(arg);
|
||||
|
@ -744,6 +721,9 @@ static int ingenic_drm_enable_vblank(struct drm_crtc *crtc)
|
|||
{
|
||||
struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
|
||||
|
||||
if (priv->no_vblank)
|
||||
return -EINVAL;
|
||||
|
||||
regmap_update_bits(priv->map, JZ_REG_LCD_CTRL,
|
||||
JZ_LCD_CTRL_EOF_IRQ, JZ_LCD_CTRL_EOF_IRQ);
|
||||
|
||||
|
@ -851,7 +831,7 @@ static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
|
|||
};
|
||||
|
||||
static struct drm_mode_config_helper_funcs ingenic_drm_mode_config_helpers = {
|
||||
.atomic_commit_tail = ingenic_drm_atomic_helper_commit_tail,
|
||||
.atomic_commit_tail = drm_atomic_helper_commit_tail,
|
||||
};
|
||||
|
||||
static void ingenic_drm_unbind_all(void *d)
|
||||
|
@ -984,9 +964,6 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
|
|||
priv->dma_hwdescs->hwdesc_pal.cmd = JZ_LCD_CMD_ENABLE_PAL
|
||||
| (sizeof(priv->dma_hwdescs->palette) / 4);
|
||||
|
||||
if (soc_info->has_osd)
|
||||
priv->ipu_plane = drm_plane_from_index(drm, 0);
|
||||
|
||||
primary = priv->soc_info->has_osd ? &priv->f1 : &priv->f0;
|
||||
|
||||
drm_plane_helper_add(primary, &ingenic_drm_plane_helper_funcs);
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
|
@ -399,14 +398,29 @@ static void kmb_irq_reset(struct drm_device *drm)
|
|||
kmb_write_lcd(to_kmb(drm), LCD_INT_ENABLE, 0);
|
||||
}
|
||||
|
||||
static int kmb_irq_install(struct drm_device *drm, unsigned int irq)
|
||||
{
|
||||
if (irq == IRQ_NOTCONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
kmb_irq_reset(drm);
|
||||
|
||||
return request_irq(irq, kmb_isr, 0, drm->driver->name, drm);
|
||||
}
|
||||
|
||||
static void kmb_irq_uninstall(struct drm_device *drm)
|
||||
{
|
||||
struct kmb_drm_private *kmb = to_kmb(drm);
|
||||
|
||||
kmb_irq_reset(drm);
|
||||
free_irq(kmb->irq_lcd, drm);
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(fops);
|
||||
|
||||
static const struct drm_driver kmb_driver = {
|
||||
.driver_features = DRIVER_GEM |
|
||||
DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.irq_handler = kmb_isr,
|
||||
.irq_preinstall = kmb_irq_reset,
|
||||
.irq_uninstall = kmb_irq_reset,
|
||||
/* GEM Operations */
|
||||
.fops = &fops,
|
||||
DRM_GEM_CMA_DRIVER_OPS_VMAP,
|
||||
|
@ -428,7 +442,7 @@ static int kmb_remove(struct platform_device *pdev)
|
|||
of_node_put(kmb->crtc.port);
|
||||
kmb->crtc.port = NULL;
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
drm_irq_uninstall(drm);
|
||||
kmb_irq_uninstall(drm);
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
pm_runtime_disable(drm->dev);
|
||||
|
||||
|
@ -518,7 +532,7 @@ static int kmb_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
ret = drm_irq_install(&kmb->drm, kmb->irq_lcd);
|
||||
ret = kmb_irq_install(&kmb->drm, kmb->irq_lcd);
|
||||
if (ret < 0) {
|
||||
drm_err(&kmb->drm, "failed to install IRQ handler\n");
|
||||
goto err_irq;
|
||||
|
|
|
@ -949,7 +949,7 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
|
|||
* is freed, it's too late.
|
||||
*/
|
||||
if (dev->irq_enabled)
|
||||
drm_irq_uninstall(dev);
|
||||
drm_legacy_irq_uninstall(dev);
|
||||
|
||||
if (dev->dev_private) {
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_ioctl.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_legacy.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_sarea.h>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
mgag200-y := mgag200_drv.o mgag200_i2c.o mgag200_mm.o mgag200_mode.o
|
||||
mgag200-y := mgag200_drv.o mgag200_i2c.o mgag200_mm.o mgag200_mode.o mgag200_pll.o
|
||||
|
||||
obj-$(CONFIG_DRM_MGAG200) += mgag200.o
|
||||
|
|
|
@ -43,6 +43,22 @@
|
|||
#define ATTR_INDEX 0x1fc0
|
||||
#define ATTR_DATA 0x1fc1
|
||||
|
||||
#define WREG_MISC(v) \
|
||||
WREG8(MGA_MISC_OUT, v)
|
||||
|
||||
#define RREG_MISC(v) \
|
||||
((v) = RREG8(MGA_MISC_IN))
|
||||
|
||||
#define WREG_MISC_MASKED(v, mask) \
|
||||
do { \
|
||||
u8 misc_; \
|
||||
u8 mask_ = (mask); \
|
||||
RREG_MISC(misc_); \
|
||||
misc_ &= ~mask_; \
|
||||
misc_ |= ((v) & mask_); \
|
||||
WREG_MISC(misc_); \
|
||||
} while (0)
|
||||
|
||||
#define WREG_ATTR(reg, v) \
|
||||
do { \
|
||||
RREG8(0x1fda); \
|
||||
|
@ -110,6 +126,48 @@
|
|||
#define MGAG200_MAX_FB_HEIGHT 4096
|
||||
#define MGAG200_MAX_FB_WIDTH 4096
|
||||
|
||||
struct mga_device;
|
||||
struct mgag200_pll;
|
||||
|
||||
/*
|
||||
* Stores parameters for programming the PLLs
|
||||
*
|
||||
* Fref: reference frequency (A: 25.175 Mhz, B: 28.361, C: XX Mhz)
|
||||
* Fo: output frequency
|
||||
* Fvco = Fref * (N / M)
|
||||
* Fo = Fvco / P
|
||||
*
|
||||
* S = [0..3]
|
||||
*/
|
||||
struct mgag200_pll_values {
|
||||
unsigned int m;
|
||||
unsigned int n;
|
||||
unsigned int p;
|
||||
unsigned int s;
|
||||
};
|
||||
|
||||
struct mgag200_pll_funcs {
|
||||
int (*compute)(struct mgag200_pll *pll, long clock, struct mgag200_pll_values *pllc);
|
||||
void (*update)(struct mgag200_pll *pll, const struct mgag200_pll_values *pllc);
|
||||
};
|
||||
|
||||
struct mgag200_pll {
|
||||
struct mga_device *mdev;
|
||||
|
||||
const struct mgag200_pll_funcs *funcs;
|
||||
};
|
||||
|
||||
struct mgag200_crtc_state {
|
||||
struct drm_crtc_state base;
|
||||
|
||||
struct mgag200_pll_values pixpllc;
|
||||
};
|
||||
|
||||
static inline struct mgag200_crtc_state *to_mgag200_crtc_state(struct drm_crtc_state *base)
|
||||
{
|
||||
return container_of(base, struct mgag200_crtc_state, base);
|
||||
}
|
||||
|
||||
#define to_mga_connector(x) container_of(x, struct mga_connector, base)
|
||||
|
||||
struct mga_i2c_chan {
|
||||
|
@ -180,8 +238,8 @@ struct mga_device {
|
|||
} g200se;
|
||||
} model;
|
||||
|
||||
|
||||
struct mga_connector connector;
|
||||
struct mgag200_pll pixpll;
|
||||
struct drm_simple_display_pipe display_pipe;
|
||||
};
|
||||
|
||||
|
@ -200,4 +258,7 @@ void mgag200_i2c_destroy(struct mga_i2c_chan *i2c);
|
|||
/* mgag200_mm.c */
|
||||
int mgag200_mm_init(struct mga_device *mdev);
|
||||
|
||||
/* mgag200_pll.c */
|
||||
int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev);
|
||||
|
||||
#endif /* __MGAG200_DRV_H__ */
|
||||
|
|
|
@ -110,712 +110,6 @@ static inline void mga_wait_busy(struct mga_device *mdev)
|
|||
} while ((status & 0x01) && time_before(jiffies, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* PLL setup
|
||||
*/
|
||||
|
||||
static int mgag200_g200_set_plls(struct mga_device *mdev, long clock)
|
||||
{
|
||||
struct drm_device *dev = &mdev->base;
|
||||
const int post_div_max = 7;
|
||||
const int in_div_min = 1;
|
||||
const int in_div_max = 6;
|
||||
const int feed_div_min = 7;
|
||||
const int feed_div_max = 127;
|
||||
u8 testm, testn;
|
||||
u8 n = 0, m = 0, p, s;
|
||||
long f_vco;
|
||||
long computed;
|
||||
long delta, tmp_delta;
|
||||
long ref_clk = mdev->model.g200.ref_clk;
|
||||
long p_clk_min = mdev->model.g200.pclk_min;
|
||||
long p_clk_max = mdev->model.g200.pclk_max;
|
||||
|
||||
if (clock > p_clk_max) {
|
||||
drm_err(dev, "Pixel Clock %ld too high\n", clock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (clock < p_clk_min >> 3)
|
||||
clock = p_clk_min >> 3;
|
||||
|
||||
f_vco = clock;
|
||||
for (p = 0;
|
||||
p <= post_div_max && f_vco < p_clk_min;
|
||||
p = (p << 1) + 1, f_vco <<= 1)
|
||||
;
|
||||
|
||||
delta = clock;
|
||||
|
||||
for (testm = in_div_min; testm <= in_div_max; testm++) {
|
||||
for (testn = feed_div_min; testn <= feed_div_max; testn++) {
|
||||
computed = ref_clk * (testn + 1) / (testm + 1);
|
||||
if (computed < f_vco)
|
||||
tmp_delta = f_vco - computed;
|
||||
else
|
||||
tmp_delta = computed - f_vco;
|
||||
if (tmp_delta < delta) {
|
||||
delta = tmp_delta;
|
||||
m = testm;
|
||||
n = testn;
|
||||
}
|
||||
}
|
||||
}
|
||||
f_vco = ref_clk * (n + 1) / (m + 1);
|
||||
if (f_vco < 100000)
|
||||
s = 0;
|
||||
else if (f_vco < 140000)
|
||||
s = 1;
|
||||
else if (f_vco < 180000)
|
||||
s = 2;
|
||||
else
|
||||
s = 3;
|
||||
|
||||
drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n",
|
||||
clock, f_vco, m, n, p, s);
|
||||
|
||||
WREG_DAC(MGA1064_PIX_PLLC_M, m);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_N, n);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_P, (p | (s << 3)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define P_ARRAY_SIZE 9
|
||||
|
||||
static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
|
||||
{
|
||||
u32 unique_rev_id = mdev->model.g200se.unique_rev_id;
|
||||
unsigned int vcomax, vcomin, pllreffreq;
|
||||
unsigned int delta, tmpdelta, permitteddelta;
|
||||
unsigned int testp, testm, testn;
|
||||
unsigned int p, m, n;
|
||||
unsigned int computed;
|
||||
unsigned int pvalues_e4[P_ARRAY_SIZE] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
|
||||
unsigned int fvv;
|
||||
unsigned int i;
|
||||
|
||||
if (unique_rev_id <= 0x03) {
|
||||
|
||||
m = n = p = 0;
|
||||
vcomax = 320000;
|
||||
vcomin = 160000;
|
||||
pllreffreq = 25000;
|
||||
|
||||
delta = 0xffffffff;
|
||||
permitteddelta = clock * 5 / 1000;
|
||||
|
||||
for (testp = 8; testp > 0; testp /= 2) {
|
||||
if (clock * testp > vcomax)
|
||||
continue;
|
||||
if (clock * testp < vcomin)
|
||||
continue;
|
||||
|
||||
for (testn = 17; testn < 256; testn++) {
|
||||
for (testm = 1; testm < 32; testm++) {
|
||||
computed = (pllreffreq * testn) /
|
||||
(testm * testp);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
m = testm - 1;
|
||||
n = testn - 1;
|
||||
p = testp - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
m = n = p = 0;
|
||||
vcomax = 1600000;
|
||||
vcomin = 800000;
|
||||
pllreffreq = 25000;
|
||||
|
||||
if (clock < 25000)
|
||||
clock = 25000;
|
||||
|
||||
clock = clock * 2;
|
||||
|
||||
delta = 0xFFFFFFFF;
|
||||
/* Permited delta is 0.5% as VESA Specification */
|
||||
permitteddelta = clock * 5 / 1000;
|
||||
|
||||
for (i = 0 ; i < P_ARRAY_SIZE ; i++) {
|
||||
testp = pvalues_e4[i];
|
||||
|
||||
if ((clock * testp) > vcomax)
|
||||
continue;
|
||||
if ((clock * testp) < vcomin)
|
||||
continue;
|
||||
|
||||
for (testn = 50; testn <= 256; testn++) {
|
||||
for (testm = 1; testm <= 32; testm++) {
|
||||
computed = (pllreffreq * testn) /
|
||||
(testm * testp);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
m = testm - 1;
|
||||
n = testn - 1;
|
||||
p = testp - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fvv = pllreffreq * (n + 1) / (m + 1);
|
||||
fvv = (fvv - 800000) / 50000;
|
||||
|
||||
if (fvv > 15)
|
||||
fvv = 15;
|
||||
|
||||
p |= (fvv << 4);
|
||||
m |= 0x80;
|
||||
|
||||
clock = clock / 2;
|
||||
}
|
||||
|
||||
if (delta > permitteddelta) {
|
||||
pr_warn("PLL delta too large\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
WREG_DAC(MGA1064_PIX_PLLC_M, m);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_N, n);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_P, p);
|
||||
|
||||
if (unique_rev_id >= 0x04) {
|
||||
WREG_DAC(0x1a, 0x09);
|
||||
msleep(20);
|
||||
WREG_DAC(0x1a, 0x01);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
|
||||
{
|
||||
unsigned int vcomax, vcomin, pllreffreq;
|
||||
unsigned int delta, tmpdelta;
|
||||
unsigned int testp, testm, testn, testp2;
|
||||
unsigned int p, m, n;
|
||||
unsigned int computed;
|
||||
int i, j, tmpcount, vcount;
|
||||
bool pll_locked = false;
|
||||
u8 tmp;
|
||||
|
||||
m = n = p = 0;
|
||||
|
||||
delta = 0xffffffff;
|
||||
|
||||
if (mdev->type == G200_EW3) {
|
||||
|
||||
vcomax = 800000;
|
||||
vcomin = 400000;
|
||||
pllreffreq = 25000;
|
||||
|
||||
for (testp = 1; testp < 8; testp++) {
|
||||
for (testp2 = 1; testp2 < 8; testp2++) {
|
||||
if (testp < testp2)
|
||||
continue;
|
||||
if ((clock * testp * testp2) > vcomax)
|
||||
continue;
|
||||
if ((clock * testp * testp2) < vcomin)
|
||||
continue;
|
||||
for (testm = 1; testm < 26; testm++) {
|
||||
for (testn = 32; testn < 2048 ; testn++) {
|
||||
computed = (pllreffreq * testn) /
|
||||
(testm * testp * testp2);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
m = ((testn & 0x100) >> 1) |
|
||||
(testm);
|
||||
n = (testn & 0xFF);
|
||||
p = ((testn & 0x600) >> 3) |
|
||||
(testp2 << 3) |
|
||||
(testp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
vcomax = 550000;
|
||||
vcomin = 150000;
|
||||
pllreffreq = 48000;
|
||||
|
||||
for (testp = 1; testp < 9; testp++) {
|
||||
if (clock * testp > vcomax)
|
||||
continue;
|
||||
if (clock * testp < vcomin)
|
||||
continue;
|
||||
|
||||
for (testm = 1; testm < 17; testm++) {
|
||||
for (testn = 1; testn < 151; testn++) {
|
||||
computed = (pllreffreq * testn) /
|
||||
(testm * testp);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
n = testn - 1;
|
||||
m = (testm - 1) |
|
||||
((n >> 1) & 0x80);
|
||||
p = testp - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= 32 && pll_locked == false; i++) {
|
||||
if (i > 0) {
|
||||
WREG8(MGAREG_CRTC_INDEX, 0x1e);
|
||||
tmp = RREG8(MGAREG_CRTC_DATA);
|
||||
if (tmp < 0xff)
|
||||
WREG8(MGAREG_CRTC_DATA, tmp+1);
|
||||
}
|
||||
|
||||
/* set pixclkdis to 1 */
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_REMHEADCTL_CLKDIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
/* select PLL Set C */
|
||||
tmp = RREG8(MGAREG_MEM_MISC_READ);
|
||||
tmp |= 0x3 << 2;
|
||||
WREG8(MGAREG_MEM_MISC_WRITE, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
/* reset the PLL */
|
||||
WREG8(DAC_INDEX, MGA1064_VREF_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~0x04;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
udelay(50);
|
||||
|
||||
/* program pixel pll register */
|
||||
WREG_DAC(MGA1064_WB_PIX_PLLC_N, n);
|
||||
WREG_DAC(MGA1064_WB_PIX_PLLC_M, m);
|
||||
WREG_DAC(MGA1064_WB_PIX_PLLC_P, p);
|
||||
|
||||
udelay(50);
|
||||
|
||||
/* turn pll on */
|
||||
WREG8(DAC_INDEX, MGA1064_VREF_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= 0x04;
|
||||
WREG_DAC(MGA1064_VREF_CTL, tmp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
/* select the pixel pll */
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
|
||||
tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
|
||||
tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
/* reset dotclock rate bit */
|
||||
WREG8(MGAREG_SEQ_INDEX, 1);
|
||||
tmp = RREG8(MGAREG_SEQ_DATA);
|
||||
tmp &= ~0x8;
|
||||
WREG8(MGAREG_SEQ_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
vcount = RREG8(MGAREG_VCOUNT);
|
||||
|
||||
for (j = 0; j < 30 && pll_locked == false; j++) {
|
||||
tmpcount = RREG8(MGAREG_VCOUNT);
|
||||
if (tmpcount < vcount)
|
||||
vcount = 0;
|
||||
if ((tmpcount - vcount) > 2)
|
||||
pll_locked = true;
|
||||
else
|
||||
udelay(5);
|
||||
}
|
||||
}
|
||||
WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
|
||||
WREG_DAC(MGA1064_REMHEADCTL, tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
|
||||
{
|
||||
unsigned int vcomax, vcomin, pllreffreq;
|
||||
unsigned int delta, tmpdelta;
|
||||
unsigned int testp, testm, testn;
|
||||
unsigned int p, m, n;
|
||||
unsigned int computed;
|
||||
u8 tmp;
|
||||
|
||||
m = n = p = 0;
|
||||
vcomax = 550000;
|
||||
vcomin = 150000;
|
||||
pllreffreq = 50000;
|
||||
|
||||
delta = 0xffffffff;
|
||||
|
||||
for (testp = 16; testp > 0; testp--) {
|
||||
if (clock * testp > vcomax)
|
||||
continue;
|
||||
if (clock * testp < vcomin)
|
||||
continue;
|
||||
|
||||
for (testn = 1; testn < 257; testn++) {
|
||||
for (testm = 1; testm < 17; testm++) {
|
||||
computed = (pllreffreq * testn) /
|
||||
(testm * testp);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
n = testn - 1;
|
||||
m = testm - 1;
|
||||
p = testp - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
tmp = RREG8(MGAREG_MEM_MISC_READ);
|
||||
tmp |= 0x3 << 2;
|
||||
WREG8(MGAREG_MEM_MISC_WRITE, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
WREG8(DAC_DATA, tmp & ~0x40);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG_DAC(MGA1064_EV_PIX_PLLC_M, m);
|
||||
WREG_DAC(MGA1064_EV_PIX_PLLC_N, n);
|
||||
WREG_DAC(MGA1064_EV_PIX_PLLC_P, p);
|
||||
|
||||
udelay(50);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
|
||||
tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
WREG8(DAC_DATA, tmp | 0x40);
|
||||
|
||||
tmp = RREG8(MGAREG_MEM_MISC_READ);
|
||||
tmp |= (0x3 << 2);
|
||||
WREG8(MGAREG_MEM_MISC_WRITE, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
|
||||
{
|
||||
unsigned int vcomax, vcomin, pllreffreq;
|
||||
unsigned int delta, tmpdelta;
|
||||
unsigned int testp, testm, testn;
|
||||
unsigned int p, m, n;
|
||||
unsigned int computed;
|
||||
int i, j, tmpcount, vcount;
|
||||
u8 tmp;
|
||||
bool pll_locked = false;
|
||||
|
||||
m = n = p = 0;
|
||||
|
||||
if (mdev->type == G200_EH3) {
|
||||
vcomax = 3000000;
|
||||
vcomin = 1500000;
|
||||
pllreffreq = 25000;
|
||||
|
||||
delta = 0xffffffff;
|
||||
|
||||
testp = 0;
|
||||
|
||||
for (testm = 150; testm >= 6; testm--) {
|
||||
if (clock * testm > vcomax)
|
||||
continue;
|
||||
if (clock * testm < vcomin)
|
||||
continue;
|
||||
for (testn = 120; testn >= 60; testn--) {
|
||||
computed = (pllreffreq * testn) / testm;
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
n = testn;
|
||||
m = testm;
|
||||
p = testp;
|
||||
}
|
||||
if (delta == 0)
|
||||
break;
|
||||
}
|
||||
if (delta == 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
vcomax = 800000;
|
||||
vcomin = 400000;
|
||||
pllreffreq = 33333;
|
||||
|
||||
delta = 0xffffffff;
|
||||
|
||||
for (testp = 16; testp > 0; testp >>= 1) {
|
||||
if (clock * testp > vcomax)
|
||||
continue;
|
||||
if (clock * testp < vcomin)
|
||||
continue;
|
||||
|
||||
for (testm = 1; testm < 33; testm++) {
|
||||
for (testn = 17; testn < 257; testn++) {
|
||||
computed = (pllreffreq * testn) /
|
||||
(testm * testp);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
n = testn - 1;
|
||||
m = (testm - 1);
|
||||
p = testp - 1;
|
||||
}
|
||||
if ((clock * testp) >= 600000)
|
||||
p |= 0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i <= 32 && pll_locked == false; i++) {
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
tmp = RREG8(MGAREG_MEM_MISC_READ);
|
||||
tmp |= 0x3 << 2;
|
||||
WREG8(MGAREG_MEM_MISC_WRITE, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
WREG_DAC(MGA1064_EH_PIX_PLLC_M, m);
|
||||
WREG_DAC(MGA1064_EH_PIX_PLLC_N, n);
|
||||
WREG_DAC(MGA1064_EH_PIX_PLLC_P, p);
|
||||
|
||||
udelay(500);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
|
||||
tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
vcount = RREG8(MGAREG_VCOUNT);
|
||||
|
||||
for (j = 0; j < 30 && pll_locked == false; j++) {
|
||||
tmpcount = RREG8(MGAREG_VCOUNT);
|
||||
if (tmpcount < vcount)
|
||||
vcount = 0;
|
||||
if ((tmpcount - vcount) > 2)
|
||||
pll_locked = true;
|
||||
else
|
||||
udelay(5);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
|
||||
{
|
||||
static const unsigned int m_div_val[] = { 1, 2, 4, 8 };
|
||||
unsigned int vcomax, vcomin, pllreffreq;
|
||||
unsigned int delta, tmpdelta;
|
||||
int testr, testn, testm, testo;
|
||||
unsigned int p, m, n;
|
||||
unsigned int computed, vco;
|
||||
int tmp;
|
||||
|
||||
m = n = p = 0;
|
||||
vcomax = 1488000;
|
||||
vcomin = 1056000;
|
||||
pllreffreq = 48000;
|
||||
|
||||
delta = 0xffffffff;
|
||||
|
||||
for (testr = 0; testr < 4; testr++) {
|
||||
if (delta == 0)
|
||||
break;
|
||||
for (testn = 5; testn < 129; testn++) {
|
||||
if (delta == 0)
|
||||
break;
|
||||
for (testm = 3; testm >= 0; testm--) {
|
||||
if (delta == 0)
|
||||
break;
|
||||
for (testo = 5; testo < 33; testo++) {
|
||||
vco = pllreffreq * (testn + 1) /
|
||||
(testr + 1);
|
||||
if (vco < vcomin)
|
||||
continue;
|
||||
if (vco > vcomax)
|
||||
continue;
|
||||
computed = vco / (m_div_val[testm] * (testo + 1));
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
m = testm | (testo << 3);
|
||||
n = testn;
|
||||
p = testr | (testr << 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_REMHEADCTL_CLKDIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
tmp = RREG8(MGAREG_MEM_MISC_READ);
|
||||
tmp |= (0x3<<2) | 0xc0;
|
||||
WREG8(MGAREG_MEM_MISC_WRITE, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
WREG_DAC(MGA1064_ER_PIX_PLLC_N, n);
|
||||
WREG_DAC(MGA1064_ER_PIX_PLLC_M, m);
|
||||
WREG_DAC(MGA1064_ER_PIX_PLLC_P, p);
|
||||
|
||||
udelay(50);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mgag200_crtc_set_plls(struct mga_device *mdev, long clock)
|
||||
{
|
||||
u8 misc;
|
||||
|
||||
switch(mdev->type) {
|
||||
case G200_PCI:
|
||||
case G200_AGP:
|
||||
return mgag200_g200_set_plls(mdev, clock);
|
||||
case G200_SE_A:
|
||||
case G200_SE_B:
|
||||
return mga_g200se_set_plls(mdev, clock);
|
||||
case G200_WB:
|
||||
case G200_EW3:
|
||||
return mga_g200wb_set_plls(mdev, clock);
|
||||
case G200_EV:
|
||||
return mga_g200ev_set_plls(mdev, clock);
|
||||
case G200_EH:
|
||||
case G200_EH3:
|
||||
return mga_g200eh_set_plls(mdev, clock);
|
||||
case G200_ER:
|
||||
return mga_g200er_set_plls(mdev, clock);
|
||||
}
|
||||
|
||||
misc = RREG8(MGA_MISC_IN);
|
||||
misc &= ~MGAREG_MISC_CLK_SEL_MASK;
|
||||
misc |= MGAREG_MISC_CLK_SEL_MGA_MSK;
|
||||
WREG8(MGA_MISC_OUT, misc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mgag200_g200wb_hold_bmc(struct mga_device *mdev)
|
||||
{
|
||||
u8 tmp;
|
||||
|
@ -1570,7 +864,9 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
struct mgag200_pll *pixpll = &mdev->pixpll;
|
||||
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
|
||||
struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
|
||||
struct drm_framebuffer *fb = plane_state->fb;
|
||||
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
|
||||
struct drm_rect fullscreen = {
|
||||
|
@ -1585,7 +881,8 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||
|
||||
mgag200_set_format_regs(mdev, fb);
|
||||
mgag200_set_mode_regs(mdev, adjusted_mode);
|
||||
mgag200_crtc_set_plls(mdev, adjusted_mode->clock);
|
||||
|
||||
pixpll->funcs->update(pixpll, &mgag200_crtc_state->pixpllc);
|
||||
|
||||
if (mdev->type == G200_ER)
|
||||
mgag200_g200er_reset_tagfifo(mdev);
|
||||
|
@ -1601,7 +898,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||
mga_crtc_load_lut(crtc);
|
||||
mgag200_enable_display(mdev);
|
||||
|
||||
mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->map[0]);
|
||||
mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->data[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1619,8 +916,13 @@ mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe,
|
|||
struct drm_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_plane *plane = plane_state->plane;
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
struct mgag200_pll *pixpll = &mdev->pixpll;
|
||||
struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
|
||||
struct drm_framebuffer *new_fb = plane_state->fb;
|
||||
struct drm_framebuffer *fb = NULL;
|
||||
int ret;
|
||||
|
||||
if (!new_fb)
|
||||
return 0;
|
||||
|
@ -1631,6 +933,13 @@ mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe,
|
|||
if (!fb || (fb->format != new_fb->format))
|
||||
crtc_state->mode_changed = true; /* update PLL settings */
|
||||
|
||||
if (crtc_state->mode_changed) {
|
||||
ret = pixpll->funcs->compute(pixpll, crtc_state->mode.clock,
|
||||
&mgag200_crtc_state->pixpllc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1650,7 +959,54 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
|
|||
return;
|
||||
|
||||
if (drm_atomic_helper_damage_merged(old_state, state, &damage))
|
||||
mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->map[0]);
|
||||
mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->data[0]);
|
||||
}
|
||||
|
||||
static struct drm_crtc_state *
|
||||
mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_crtc_state *crtc_state = crtc->state;
|
||||
struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
|
||||
struct mgag200_crtc_state *new_mgag200_crtc_state;
|
||||
|
||||
if (!crtc_state)
|
||||
return NULL;
|
||||
|
||||
new_mgag200_crtc_state = kzalloc(sizeof(*new_mgag200_crtc_state), GFP_KERNEL);
|
||||
if (!new_mgag200_crtc_state)
|
||||
return NULL;
|
||||
__drm_atomic_helper_crtc_duplicate_state(crtc, &new_mgag200_crtc_state->base);
|
||||
|
||||
memcpy(&new_mgag200_crtc_state->pixpllc, &mgag200_crtc_state->pixpllc,
|
||||
sizeof(new_mgag200_crtc_state->pixpllc));
|
||||
|
||||
return &new_mgag200_crtc_state->base;
|
||||
}
|
||||
|
||||
static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_crtc_state *crtc_state)
|
||||
{
|
||||
struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
|
||||
|
||||
__drm_atomic_helper_crtc_destroy_state(&mgag200_crtc_state->base);
|
||||
kfree(mgag200_crtc_state);
|
||||
}
|
||||
|
||||
static void mgag200_simple_display_pipe_reset_crtc(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct mgag200_crtc_state *mgag200_crtc_state;
|
||||
|
||||
if (crtc->state) {
|
||||
mgag200_simple_display_pipe_destroy_crtc_state(pipe, crtc->state);
|
||||
crtc->state = NULL; /* must be set to NULL here */
|
||||
}
|
||||
|
||||
mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL);
|
||||
if (!mgag200_crtc_state)
|
||||
return;
|
||||
__drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base);
|
||||
}
|
||||
|
||||
static const struct drm_simple_display_pipe_funcs
|
||||
|
@ -1660,6 +1016,9 @@ mgag200_simple_display_pipe_funcs = {
|
|||
.disable = mgag200_simple_display_pipe_disable,
|
||||
.check = mgag200_simple_display_pipe_check,
|
||||
.update = mgag200_simple_display_pipe_update,
|
||||
.reset_crtc = mgag200_simple_display_pipe_reset_crtc,
|
||||
.duplicate_crtc_state = mgag200_simple_display_pipe_duplicate_crtc_state,
|
||||
.destroy_crtc_state = mgag200_simple_display_pipe_destroy_crtc_state,
|
||||
DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
|
||||
};
|
||||
|
||||
|
@ -1726,6 +1085,10 @@ int mgag200_modeset_init(struct mga_device *mdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = mgag200_pixpll_init(&mdev->pixpll, mdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_simple_display_pipe_init(dev, pipe,
|
||||
&mgag200_simple_display_pipe_funcs,
|
||||
mgag200_simple_display_pipe_formats,
|
||||
|
|
992
drivers/gpu/drm/mgag200/mgag200_pll.c
Normal file
992
drivers/gpu/drm/mgag200/mgag200_pll.c
Normal file
|
@ -0,0 +1,992 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "mgag200_drv.h"
|
||||
|
||||
/*
|
||||
* G200
|
||||
*/
|
||||
|
||||
static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock,
|
||||
struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
struct mga_device *mdev = pixpll->mdev;
|
||||
struct drm_device *dev = &mdev->base;
|
||||
const int post_div_max = 7;
|
||||
const int in_div_min = 1;
|
||||
const int in_div_max = 6;
|
||||
const int feed_div_min = 7;
|
||||
const int feed_div_max = 127;
|
||||
u8 testp, testm, testn;
|
||||
u8 n = 0, m = 0, p, s;
|
||||
long f_vco;
|
||||
long computed;
|
||||
long delta, tmp_delta;
|
||||
long ref_clk = mdev->model.g200.ref_clk;
|
||||
long p_clk_min = mdev->model.g200.pclk_min;
|
||||
long p_clk_max = mdev->model.g200.pclk_max;
|
||||
|
||||
if (clock > p_clk_max) {
|
||||
drm_err(dev, "Pixel Clock %ld too high\n", clock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (clock < p_clk_min >> 3)
|
||||
clock = p_clk_min >> 3;
|
||||
|
||||
f_vco = clock;
|
||||
for (testp = 0;
|
||||
testp <= post_div_max && f_vco < p_clk_min;
|
||||
testp = (testp << 1) + 1, f_vco <<= 1)
|
||||
;
|
||||
p = testp + 1;
|
||||
|
||||
delta = clock;
|
||||
|
||||
for (testm = in_div_min; testm <= in_div_max; testm++) {
|
||||
for (testn = feed_div_min; testn <= feed_div_max; testn++) {
|
||||
computed = ref_clk * (testn + 1) / (testm + 1);
|
||||
if (computed < f_vco)
|
||||
tmp_delta = f_vco - computed;
|
||||
else
|
||||
tmp_delta = computed - f_vco;
|
||||
if (tmp_delta < delta) {
|
||||
delta = tmp_delta;
|
||||
m = testm + 1;
|
||||
n = testn + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
f_vco = ref_clk * n / m;
|
||||
if (f_vco < 100000)
|
||||
s = 0;
|
||||
else if (f_vco < 140000)
|
||||
s = 1;
|
||||
else if (f_vco < 180000)
|
||||
s = 2;
|
||||
else
|
||||
s = 3;
|
||||
|
||||
drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n",
|
||||
clock, f_vco, m, n, p, s);
|
||||
|
||||
pixpllc->m = m;
|
||||
pixpllc->n = n;
|
||||
pixpllc->p = p;
|
||||
pixpllc->s = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mgag200_pixpll_update_g200(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
struct mga_device *mdev = pixpll->mdev;
|
||||
unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
|
||||
u8 xpixpllcm, xpixpllcn, xpixpllcp;
|
||||
|
||||
pixpllcm = pixpllc->m - 1;
|
||||
pixpllcn = pixpllc->n - 1;
|
||||
pixpllcp = pixpllc->p - 1;
|
||||
pixpllcs = pixpllc->s;
|
||||
|
||||
xpixpllcm = pixpllcm;
|
||||
xpixpllcn = pixpllcn;
|
||||
xpixpllcp = (pixpllcs << 3) | pixpllcp;
|
||||
|
||||
WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
|
||||
|
||||
WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
|
||||
}
|
||||
|
||||
static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200 = {
|
||||
.compute = mgag200_pixpll_compute_g200,
|
||||
.update = mgag200_pixpll_update_g200,
|
||||
};
|
||||
|
||||
/*
|
||||
* G200SE
|
||||
*/
|
||||
|
||||
static int mgag200_pixpll_compute_g200se_00(struct mgag200_pll *pixpll, long clock,
|
||||
struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
static const unsigned int vcomax = 320000;
|
||||
static const unsigned int vcomin = 160000;
|
||||
static const unsigned int pllreffreq = 25000;
|
||||
|
||||
unsigned int delta, tmpdelta, permitteddelta;
|
||||
unsigned int testp, testm, testn;
|
||||
unsigned int p, m, n, s;
|
||||
unsigned int computed;
|
||||
|
||||
m = n = p = s = 0;
|
||||
permitteddelta = clock * 5 / 1000;
|
||||
|
||||
for (testp = 8; testp > 0; testp /= 2) {
|
||||
if (clock * testp > vcomax)
|
||||
continue;
|
||||
if (clock * testp < vcomin)
|
||||
continue;
|
||||
|
||||
for (testn = 17; testn < 256; testn++) {
|
||||
for (testm = 1; testm < 32; testm++) {
|
||||
computed = (pllreffreq * testn) / (testm * testp);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
m = testm;
|
||||
n = testn;
|
||||
p = testp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delta > permitteddelta) {
|
||||
pr_warn("PLL delta too large\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pixpllc->m = m;
|
||||
pixpllc->n = n;
|
||||
pixpllc->p = p;
|
||||
pixpllc->s = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mgag200_pixpll_update_g200se_00(struct mgag200_pll *pixpll,
|
||||
const struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
|
||||
u8 xpixpllcm, xpixpllcn, xpixpllcp;
|
||||
struct mga_device *mdev = pixpll->mdev;
|
||||
|
||||
pixpllcm = pixpllc->m - 1;
|
||||
pixpllcn = pixpllc->n - 1;
|
||||
pixpllcp = pixpllc->p - 1;
|
||||
pixpllcs = pixpllc->s;
|
||||
|
||||
xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
|
||||
xpixpllcn = pixpllcn;
|
||||
xpixpllcp = (pixpllcs << 3) | pixpllcp;
|
||||
|
||||
WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
|
||||
|
||||
WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
|
||||
}
|
||||
|
||||
static int mgag200_pixpll_compute_g200se_04(struct mgag200_pll *pixpll, long clock,
|
||||
struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
static const unsigned int vcomax = 1600000;
|
||||
static const unsigned int vcomin = 800000;
|
||||
static const unsigned int pllreffreq = 25000;
|
||||
static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
|
||||
|
||||
unsigned int delta, tmpdelta, permitteddelta;
|
||||
unsigned int testp, testm, testn;
|
||||
unsigned int p, m, n, s;
|
||||
unsigned int computed;
|
||||
unsigned int fvv;
|
||||
unsigned int i;
|
||||
|
||||
m = n = p = s = 0;
|
||||
delta = 0xffffffff;
|
||||
|
||||
if (clock < 25000)
|
||||
clock = 25000;
|
||||
clock = clock * 2;
|
||||
|
||||
/* Permited delta is 0.5% as VESA Specification */
|
||||
permitteddelta = clock * 5 / 1000;
|
||||
|
||||
for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
|
||||
testp = pvalues_e4[i];
|
||||
|
||||
if ((clock * testp) > vcomax)
|
||||
continue;
|
||||
if ((clock * testp) < vcomin)
|
||||
continue;
|
||||
|
||||
for (testn = 50; testn <= 256; testn++) {
|
||||
for (testm = 1; testm <= 32; testm++) {
|
||||
computed = (pllreffreq * testn) / (testm * testp);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
m = testm;
|
||||
n = testn;
|
||||
p = testp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fvv = pllreffreq * n / m;
|
||||
fvv = (fvv - 800000) / 50000;
|
||||
if (fvv > 15)
|
||||
fvv = 15;
|
||||
s = fvv << 1;
|
||||
|
||||
if (delta > permitteddelta) {
|
||||
pr_warn("PLL delta too large\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pixpllc->m = m;
|
||||
pixpllc->n = n;
|
||||
pixpllc->p = p;
|
||||
pixpllc->s = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll,
|
||||
const struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
|
||||
u8 xpixpllcm, xpixpllcn, xpixpllcp;
|
||||
struct mga_device *mdev = pixpll->mdev;
|
||||
|
||||
pixpllcm = pixpllc->m - 1;
|
||||
pixpllcn = pixpllc->n - 1;
|
||||
pixpllcp = pixpllc->p - 1;
|
||||
pixpllcs = pixpllc->s;
|
||||
|
||||
xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
|
||||
xpixpllcn = pixpllcn;
|
||||
xpixpllcp = (pixpllcs << 3) | pixpllcp;
|
||||
|
||||
WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
|
||||
|
||||
WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
|
||||
|
||||
WREG_DAC(0x1a, 0x09);
|
||||
msleep(20);
|
||||
WREG_DAC(0x1a, 0x01);
|
||||
}
|
||||
|
||||
static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_00 = {
|
||||
.compute = mgag200_pixpll_compute_g200se_00,
|
||||
.update = mgag200_pixpll_update_g200se_00,
|
||||
};
|
||||
|
||||
static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_04 = {
|
||||
.compute = mgag200_pixpll_compute_g200se_04,
|
||||
.update = mgag200_pixpll_update_g200se_04,
|
||||
};
|
||||
|
||||
/*
|
||||
* G200WB
|
||||
*/
|
||||
|
||||
static int mgag200_pixpll_compute_g200wb(struct mgag200_pll *pixpll, long clock,
|
||||
struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
static const unsigned int vcomax = 550000;
|
||||
static const unsigned int vcomin = 150000;
|
||||
static const unsigned int pllreffreq = 48000;
|
||||
|
||||
unsigned int delta, tmpdelta;
|
||||
unsigned int testp, testm, testn;
|
||||
unsigned int p, m, n, s;
|
||||
unsigned int computed;
|
||||
|
||||
m = n = p = s = 0;
|
||||
delta = 0xffffffff;
|
||||
|
||||
for (testp = 1; testp < 9; testp++) {
|
||||
if (clock * testp > vcomax)
|
||||
continue;
|
||||
if (clock * testp < vcomin)
|
||||
continue;
|
||||
|
||||
for (testm = 1; testm < 17; testm++) {
|
||||
for (testn = 1; testn < 151; testn++) {
|
||||
computed = (pllreffreq * testn) / (testm * testp);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
n = testn;
|
||||
m = testm;
|
||||
p = testp;
|
||||
s = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pixpllc->m = m;
|
||||
pixpllc->n = n;
|
||||
pixpllc->p = p;
|
||||
pixpllc->s = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
|
||||
u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
|
||||
int i, j, tmpcount, vcount;
|
||||
struct mga_device *mdev = pixpll->mdev;
|
||||
bool pll_locked = false;
|
||||
|
||||
pixpllcm = pixpllc->m - 1;
|
||||
pixpllcn = pixpllc->n - 1;
|
||||
pixpllcp = pixpllc->p - 1;
|
||||
pixpllcs = pixpllc->s;
|
||||
|
||||
xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
|
||||
xpixpllcn = pixpllcn;
|
||||
xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp;
|
||||
|
||||
WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
|
||||
|
||||
for (i = 0; i <= 32 && pll_locked == false; i++) {
|
||||
if (i > 0) {
|
||||
WREG8(MGAREG_CRTC_INDEX, 0x1e);
|
||||
tmp = RREG8(MGAREG_CRTC_DATA);
|
||||
if (tmp < 0xff)
|
||||
WREG8(MGAREG_CRTC_DATA, tmp+1);
|
||||
}
|
||||
|
||||
/* set pixclkdis to 1 */
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_REMHEADCTL_CLKDIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
/* select PLL Set C */
|
||||
tmp = RREG8(MGAREG_MEM_MISC_READ);
|
||||
tmp |= 0x3 << 2;
|
||||
WREG8(MGAREG_MEM_MISC_WRITE, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
/* reset the PLL */
|
||||
WREG8(DAC_INDEX, MGA1064_VREF_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~0x04;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
udelay(50);
|
||||
|
||||
/* program pixel pll register */
|
||||
WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
|
||||
|
||||
udelay(50);
|
||||
|
||||
/* turn pll on */
|
||||
WREG8(DAC_INDEX, MGA1064_VREF_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= 0x04;
|
||||
WREG_DAC(MGA1064_VREF_CTL, tmp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
/* select the pixel pll */
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
|
||||
tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
|
||||
tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
/* reset dotclock rate bit */
|
||||
WREG8(MGAREG_SEQ_INDEX, 1);
|
||||
tmp = RREG8(MGAREG_SEQ_DATA);
|
||||
tmp &= ~0x8;
|
||||
WREG8(MGAREG_SEQ_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
vcount = RREG8(MGAREG_VCOUNT);
|
||||
|
||||
for (j = 0; j < 30 && pll_locked == false; j++) {
|
||||
tmpcount = RREG8(MGAREG_VCOUNT);
|
||||
if (tmpcount < vcount)
|
||||
vcount = 0;
|
||||
if ((tmpcount - vcount) > 2)
|
||||
pll_locked = true;
|
||||
else
|
||||
udelay(5);
|
||||
}
|
||||
}
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
|
||||
WREG_DAC(MGA1064_REMHEADCTL, tmp);
|
||||
}
|
||||
|
||||
static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200wb = {
|
||||
.compute = mgag200_pixpll_compute_g200wb,
|
||||
.update = mgag200_pixpll_update_g200wb,
|
||||
};
|
||||
|
||||
/*
|
||||
* G200EV
|
||||
*/
|
||||
|
||||
static int mgag200_pixpll_compute_g200ev(struct mgag200_pll *pixpll, long clock,
|
||||
struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
static const unsigned int vcomax = 550000;
|
||||
static const unsigned int vcomin = 150000;
|
||||
static const unsigned int pllreffreq = 50000;
|
||||
|
||||
unsigned int delta, tmpdelta;
|
||||
unsigned int testp, testm, testn;
|
||||
unsigned int p, m, n, s;
|
||||
unsigned int computed;
|
||||
|
||||
m = n = p = s = 0;
|
||||
delta = 0xffffffff;
|
||||
|
||||
for (testp = 16; testp > 0; testp--) {
|
||||
if (clock * testp > vcomax)
|
||||
continue;
|
||||
if (clock * testp < vcomin)
|
||||
continue;
|
||||
|
||||
for (testn = 1; testn < 257; testn++) {
|
||||
for (testm = 1; testm < 17; testm++) {
|
||||
computed = (pllreffreq * testn) /
|
||||
(testm * testp);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
n = testn;
|
||||
m = testm;
|
||||
p = testp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pixpllc->m = m;
|
||||
pixpllc->n = n;
|
||||
pixpllc->p = p;
|
||||
pixpllc->s = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mgag200_pixpll_update_g200ev(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
|
||||
u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
|
||||
struct mga_device *mdev = pixpll->mdev;
|
||||
|
||||
pixpllcm = pixpllc->m - 1;
|
||||
pixpllcn = pixpllc->n - 1;
|
||||
pixpllcp = pixpllc->p - 1;
|
||||
pixpllcs = pixpllc->s;
|
||||
|
||||
xpixpllcm = pixpllcm;
|
||||
xpixpllcn = pixpllcn;
|
||||
xpixpllcp = (pixpllcs << 3) | pixpllcp;
|
||||
|
||||
WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
tmp = RREG8(MGAREG_MEM_MISC_READ);
|
||||
tmp |= 0x3 << 2;
|
||||
WREG8(MGAREG_MEM_MISC_WRITE, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
WREG8(DAC_DATA, tmp & ~0x40);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm);
|
||||
WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn);
|
||||
WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp);
|
||||
|
||||
udelay(50);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
|
||||
tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
WREG8(DAC_DATA, tmp | 0x40);
|
||||
|
||||
tmp = RREG8(MGAREG_MEM_MISC_READ);
|
||||
tmp |= (0x3 << 2);
|
||||
WREG8(MGAREG_MEM_MISC_WRITE, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
}
|
||||
|
||||
static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ev = {
|
||||
.compute = mgag200_pixpll_compute_g200ev,
|
||||
.update = mgag200_pixpll_update_g200ev,
|
||||
};
|
||||
|
||||
/*
|
||||
* G200EH
|
||||
*/
|
||||
|
||||
static int mgag200_pixpll_compute_g200eh(struct mgag200_pll *pixpll, long clock,
|
||||
struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
static const unsigned int vcomax = 800000;
|
||||
static const unsigned int vcomin = 400000;
|
||||
static const unsigned int pllreffreq = 33333;
|
||||
|
||||
unsigned int delta, tmpdelta;
|
||||
unsigned int testp, testm, testn;
|
||||
unsigned int p, m, n, s;
|
||||
unsigned int computed;
|
||||
|
||||
m = n = p = s = 0;
|
||||
delta = 0xffffffff;
|
||||
|
||||
for (testp = 16; testp > 0; testp >>= 1) {
|
||||
if (clock * testp > vcomax)
|
||||
continue;
|
||||
if (clock * testp < vcomin)
|
||||
continue;
|
||||
|
||||
for (testm = 1; testm < 33; testm++) {
|
||||
for (testn = 17; testn < 257; testn++) {
|
||||
computed = (pllreffreq * testn) / (testm * testp);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
n = testn;
|
||||
m = testm;
|
||||
p = testp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pixpllc->m = m;
|
||||
pixpllc->n = n;
|
||||
pixpllc->p = p;
|
||||
pixpllc->s = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mgag200_pixpll_update_g200eh(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
|
||||
u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
|
||||
int i, j, tmpcount, vcount;
|
||||
struct mga_device *mdev = pixpll->mdev;
|
||||
bool pll_locked = false;
|
||||
|
||||
pixpllcm = pixpllc->m - 1;
|
||||
pixpllcn = pixpllc->n - 1;
|
||||
pixpllcp = pixpllc->p - 1;
|
||||
pixpllcs = pixpllc->s;
|
||||
|
||||
xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
|
||||
xpixpllcn = pixpllcn;
|
||||
xpixpllcp = (pixpllcs << 3) | pixpllcp;
|
||||
|
||||
WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
|
||||
|
||||
for (i = 0; i <= 32 && pll_locked == false; i++) {
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
tmp = RREG8(MGAREG_MEM_MISC_READ);
|
||||
tmp |= 0x3 << 2;
|
||||
WREG8(MGAREG_MEM_MISC_WRITE, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm);
|
||||
WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn);
|
||||
WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
|
||||
tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
vcount = RREG8(MGAREG_VCOUNT);
|
||||
|
||||
for (j = 0; j < 30 && pll_locked == false; j++) {
|
||||
tmpcount = RREG8(MGAREG_VCOUNT);
|
||||
if (tmpcount < vcount)
|
||||
vcount = 0;
|
||||
if ((tmpcount - vcount) > 2)
|
||||
pll_locked = true;
|
||||
else
|
||||
udelay(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh = {
|
||||
.compute = mgag200_pixpll_compute_g200eh,
|
||||
.update = mgag200_pixpll_update_g200eh,
|
||||
};
|
||||
|
||||
/*
|
||||
* G200EH3
|
||||
*/
|
||||
|
||||
static int mgag200_pixpll_compute_g200eh3(struct mgag200_pll *pixpll, long clock,
|
||||
struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
static const unsigned int vcomax = 3000000;
|
||||
static const unsigned int vcomin = 1500000;
|
||||
static const unsigned int pllreffreq = 25000;
|
||||
|
||||
unsigned int delta, tmpdelta;
|
||||
unsigned int testp, testm, testn;
|
||||
unsigned int p, m, n, s;
|
||||
unsigned int computed;
|
||||
|
||||
m = n = p = s = 0;
|
||||
delta = 0xffffffff;
|
||||
testp = 0;
|
||||
|
||||
for (testm = 150; testm >= 6; testm--) {
|
||||
if (clock * testm > vcomax)
|
||||
continue;
|
||||
if (clock * testm < vcomin)
|
||||
continue;
|
||||
for (testn = 120; testn >= 60; testn--) {
|
||||
computed = (pllreffreq * testn) / testm;
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
n = testn + 1;
|
||||
m = testm + 1;
|
||||
p = testp + 1;
|
||||
}
|
||||
if (delta == 0)
|
||||
break;
|
||||
}
|
||||
if (delta == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
pixpllc->m = m;
|
||||
pixpllc->n = n;
|
||||
pixpllc->p = p;
|
||||
pixpllc->s = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh3 = {
|
||||
.compute = mgag200_pixpll_compute_g200eh3,
|
||||
.update = mgag200_pixpll_update_g200eh, // same as G200EH
|
||||
};
|
||||
|
||||
/*
|
||||
* G200ER
|
||||
*/
|
||||
|
||||
static int mgag200_pixpll_compute_g200er(struct mgag200_pll *pixpll, long clock,
|
||||
struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
static const unsigned int vcomax = 1488000;
|
||||
static const unsigned int vcomin = 1056000;
|
||||
static const unsigned int pllreffreq = 48000;
|
||||
static const unsigned int m_div_val[] = { 1, 2, 4, 8 };
|
||||
|
||||
unsigned int delta, tmpdelta;
|
||||
int testr, testn, testm, testo;
|
||||
unsigned int p, m, n, s;
|
||||
unsigned int computed, vco;
|
||||
|
||||
m = n = p = s = 0;
|
||||
delta = 0xffffffff;
|
||||
|
||||
for (testr = 0; testr < 4; testr++) {
|
||||
if (delta == 0)
|
||||
break;
|
||||
for (testn = 5; testn < 129; testn++) {
|
||||
if (delta == 0)
|
||||
break;
|
||||
for (testm = 3; testm >= 0; testm--) {
|
||||
if (delta == 0)
|
||||
break;
|
||||
for (testo = 5; testo < 33; testo++) {
|
||||
vco = pllreffreq * (testn + 1) /
|
||||
(testr + 1);
|
||||
if (vco < vcomin)
|
||||
continue;
|
||||
if (vco > vcomax)
|
||||
continue;
|
||||
computed = vco / (m_div_val[testm] * (testo + 1));
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
m = (testm | (testo << 3)) + 1;
|
||||
n = testn + 1;
|
||||
p = testr + 1;
|
||||
s = testr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pixpllc->m = m;
|
||||
pixpllc->n = n;
|
||||
pixpllc->p = p;
|
||||
pixpllc->s = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mgag200_pixpll_update_g200er(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
|
||||
u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
|
||||
struct mga_device *mdev = pixpll->mdev;
|
||||
|
||||
pixpllcm = pixpllc->m - 1;
|
||||
pixpllcn = pixpllc->n - 1;
|
||||
pixpllcp = pixpllc->p - 1;
|
||||
pixpllcs = pixpllc->s;
|
||||
|
||||
xpixpllcm = pixpllcm;
|
||||
xpixpllcn = pixpllcn;
|
||||
xpixpllcp = (pixpllcs << 3) | pixpllcp;
|
||||
|
||||
WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp |= MGA1064_REMHEADCTL_CLKDIS;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
tmp = RREG8(MGAREG_MEM_MISC_READ);
|
||||
tmp |= (0x3<<2) | 0xc0;
|
||||
WREG8(MGAREG_MEM_MISC_WRITE, tmp);
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
|
||||
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
|
||||
WREG8(DAC_DATA, tmp);
|
||||
|
||||
udelay(500);
|
||||
|
||||
WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn);
|
||||
WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm);
|
||||
WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp);
|
||||
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200er = {
|
||||
.compute = mgag200_pixpll_compute_g200er,
|
||||
.update = mgag200_pixpll_update_g200er,
|
||||
};
|
||||
|
||||
/*
|
||||
* G200EW3
|
||||
*/
|
||||
|
||||
static int mgag200_pixpll_compute_g200ew3(struct mgag200_pll *pixpll, long clock,
|
||||
struct mgag200_pll_values *pixpllc)
|
||||
{
|
||||
static const unsigned int vcomax = 800000;
|
||||
static const unsigned int vcomin = 400000;
|
||||
static const unsigned int pllreffreq = 25000;
|
||||
|
||||
unsigned int delta, tmpdelta;
|
||||
unsigned int testp, testm, testn, testp2;
|
||||
unsigned int p, m, n, s;
|
||||
unsigned int computed;
|
||||
|
||||
m = n = p = s = 0;
|
||||
delta = 0xffffffff;
|
||||
|
||||
for (testp = 1; testp < 8; testp++) {
|
||||
for (testp2 = 1; testp2 < 8; testp2++) {
|
||||
if (testp < testp2)
|
||||
continue;
|
||||
if ((clock * testp * testp2) > vcomax)
|
||||
continue;
|
||||
if ((clock * testp * testp2) < vcomin)
|
||||
continue;
|
||||
for (testm = 1; testm < 26; testm++) {
|
||||
for (testn = 32; testn < 2048 ; testn++) {
|
||||
computed = (pllreffreq * testn) / (testm * testp * testp2);
|
||||
if (computed > clock)
|
||||
tmpdelta = computed - clock;
|
||||
else
|
||||
tmpdelta = clock - computed;
|
||||
if (tmpdelta < delta) {
|
||||
delta = tmpdelta;
|
||||
m = testm + 1;
|
||||
n = testn + 1;
|
||||
p = testp + 1;
|
||||
s = testp2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pixpllc->m = m;
|
||||
pixpllc->n = n;
|
||||
pixpllc->p = p;
|
||||
pixpllc->s = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = {
|
||||
.compute = mgag200_pixpll_compute_g200ew3,
|
||||
.update = mgag200_pixpll_update_g200wb, // same as G200WB
|
||||
};
|
||||
|
||||
/*
|
||||
* PLL initialization
|
||||
*/
|
||||
|
||||
int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev)
|
||||
{
|
||||
struct drm_device *dev = &mdev->base;
|
||||
|
||||
pixpll->mdev = mdev;
|
||||
|
||||
switch (mdev->type) {
|
||||
case G200_PCI:
|
||||
case G200_AGP:
|
||||
pixpll->funcs = &mgag200_pixpll_funcs_g200;
|
||||
break;
|
||||
case G200_SE_A:
|
||||
case G200_SE_B:
|
||||
if (mdev->model.g200se.unique_rev_id >= 0x04)
|
||||
pixpll->funcs = &mgag200_pixpll_funcs_g200se_04;
|
||||
else
|
||||
pixpll->funcs = &mgag200_pixpll_funcs_g200se_00;
|
||||
break;
|
||||
case G200_WB:
|
||||
pixpll->funcs = &mgag200_pixpll_funcs_g200wb;
|
||||
break;
|
||||
case G200_EV:
|
||||
pixpll->funcs = &mgag200_pixpll_funcs_g200ev;
|
||||
break;
|
||||
case G200_EH:
|
||||
pixpll->funcs = &mgag200_pixpll_funcs_g200eh;
|
||||
break;
|
||||
case G200_EH3:
|
||||
pixpll->funcs = &mgag200_pixpll_funcs_g200eh3;
|
||||
break;
|
||||
case G200_ER:
|
||||
pixpll->funcs = &mgag200_pixpll_funcs_g200er;
|
||||
break;
|
||||
case G200_EW3:
|
||||
pixpll->funcs = &mgag200_pixpll_funcs_g200ew3;
|
||||
break;
|
||||
default:
|
||||
drm_err(dev, "unknown device type %d\n", mdev->type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -222,11 +222,10 @@
|
|||
|
||||
#define MGAREG_MISC_IOADSEL (0x1 << 0)
|
||||
#define MGAREG_MISC_RAMMAPEN (0x1 << 1)
|
||||
#define MGAREG_MISC_CLK_SEL_MASK GENMASK(3, 2)
|
||||
#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2)
|
||||
#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2)
|
||||
#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2)
|
||||
#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2)
|
||||
#define MGAREG_MISC_CLKSEL_MASK GENMASK(3, 2)
|
||||
#define MGAREG_MISC_CLKSEL_VGA25 (0x0 << 2)
|
||||
#define MGAREG_MISC_CLKSEL_VGA28 (0x1 << 2)
|
||||
#define MGAREG_MISC_CLKSEL_MGA (0x3 << 2)
|
||||
#define MGAREG_MISC_VIDEO_DIS (0x1 << 4)
|
||||
#define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5)
|
||||
#define MGAREG_MISC_HSYNCPOL BIT(6)
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_ioctl.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_prime.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
@ -201,6 +200,71 @@ void msm_rmw(void __iomem *addr, u32 mask, u32 or)
|
|||
msm_writel(val | or, addr);
|
||||
}
|
||||
|
||||
static irqreturn_t msm_irq(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = arg;
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_kms *kms = priv->kms;
|
||||
|
||||
BUG_ON(!kms);
|
||||
|
||||
return kms->funcs->irq(kms);
|
||||
}
|
||||
|
||||
static void msm_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_kms *kms = priv->kms;
|
||||
|
||||
BUG_ON(!kms);
|
||||
|
||||
kms->funcs->irq_preinstall(kms);
|
||||
}
|
||||
|
||||
static int msm_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_kms *kms = priv->kms;
|
||||
|
||||
BUG_ON(!kms);
|
||||
|
||||
if (kms->funcs->irq_postinstall)
|
||||
return kms->funcs->irq_postinstall(kms);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_irq_install(struct drm_device *dev, unsigned int irq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (irq == IRQ_NOTCONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
msm_irq_preinstall(dev);
|
||||
|
||||
ret = request_irq(irq, msm_irq, 0, dev->driver->name, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = msm_irq_postinstall(dev);
|
||||
if (ret) {
|
||||
free_irq(irq, dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void msm_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_kms *kms = priv->kms;
|
||||
|
||||
kms->funcs->irq_uninstall(kms);
|
||||
free_irq(kms->irq, dev);
|
||||
}
|
||||
|
||||
struct msm_vblank_work {
|
||||
struct work_struct work;
|
||||
int crtc_id;
|
||||
|
@ -265,7 +329,7 @@ static int msm_drm_uninit(struct device *dev)
|
|||
}
|
||||
|
||||
/* We must cancel and cleanup any pending vblank enable/disable
|
||||
* work before drm_irq_uninstall() to avoid work re-enabling an
|
||||
* work before msm_irq_uninstall() to avoid work re-enabling an
|
||||
* irq after uninstall has disabled it.
|
||||
*/
|
||||
|
||||
|
@ -294,7 +358,7 @@ static int msm_drm_uninit(struct device *dev)
|
|||
drm_mode_config_cleanup(ddev);
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
drm_irq_uninstall(ddev);
|
||||
msm_irq_uninstall(ddev);
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
if (kms && kms->funcs)
|
||||
|
@ -553,7 +617,7 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
|
|||
|
||||
if (kms) {
|
||||
pm_runtime_get_sync(dev);
|
||||
ret = drm_irq_install(ddev, kms->irq);
|
||||
ret = msm_irq_install(ddev, kms->irq);
|
||||
pm_runtime_put_sync(dev);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev, "failed to install IRQ handler\n");
|
||||
|
@ -662,43 +726,6 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file)
|
|||
context_close(ctx);
|
||||
}
|
||||
|
||||
static irqreturn_t msm_irq(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = arg;
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_kms *kms = priv->kms;
|
||||
BUG_ON(!kms);
|
||||
return kms->funcs->irq(kms);
|
||||
}
|
||||
|
||||
static void msm_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_kms *kms = priv->kms;
|
||||
BUG_ON(!kms);
|
||||
kms->funcs->irq_preinstall(kms);
|
||||
}
|
||||
|
||||
static int msm_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_kms *kms = priv->kms;
|
||||
BUG_ON(!kms);
|
||||
|
||||
if (kms->funcs->irq_postinstall)
|
||||
return kms->funcs->irq_postinstall(kms);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void msm_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_kms *kms = priv->kms;
|
||||
BUG_ON(!kms);
|
||||
kms->funcs->irq_uninstall(kms);
|
||||
}
|
||||
|
||||
int msm_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
@ -1051,10 +1078,6 @@ static const struct drm_driver msm_driver = {
|
|||
.open = msm_open,
|
||||
.postclose = msm_postclose,
|
||||
.lastclose = drm_fb_helper_lastclose,
|
||||
.irq_handler = msm_irq,
|
||||
.irq_preinstall = msm_irq_preinstall,
|
||||
.irq_postinstall = msm_irq_postinstall,
|
||||
.irq_uninstall = msm_irq_uninstall,
|
||||
.dumb_create = msm_gem_dumb_create,
|
||||
.dumb_map_offset = msm_gem_dumb_map_offset,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
|
|
|
@ -150,7 +150,7 @@ struct msm_kms {
|
|||
const struct msm_kms_funcs *funcs;
|
||||
struct drm_device *dev;
|
||||
|
||||
/* irq number to be passed on to drm_irq_install */
|
||||
/* irq number to be passed on to msm_irq_install */
|
||||
int irq;
|
||||
|
||||
/* mapper-id used to request GEM buffer mapped for scanout: */
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_mode_config.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
@ -153,6 +152,49 @@ static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t mxsfb_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct drm_device *drm = data;
|
||||
struct mxsfb_drm_private *mxsfb = drm->dev_private;
|
||||
u32 reg;
|
||||
|
||||
reg = readl(mxsfb->base + LCDC_CTRL1);
|
||||
|
||||
if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
|
||||
drm_crtc_handle_vblank(&mxsfb->crtc);
|
||||
|
||||
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void mxsfb_irq_disable(struct drm_device *drm)
|
||||
{
|
||||
struct mxsfb_drm_private *mxsfb = drm->dev_private;
|
||||
|
||||
mxsfb_enable_axi_clk(mxsfb);
|
||||
mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc);
|
||||
mxsfb_disable_axi_clk(mxsfb);
|
||||
}
|
||||
|
||||
static int mxsfb_irq_install(struct drm_device *dev, int irq)
|
||||
{
|
||||
if (irq == IRQ_NOTCONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
mxsfb_irq_disable(dev);
|
||||
|
||||
return request_irq(irq, mxsfb_irq_handler, 0, dev->driver->name, dev);
|
||||
}
|
||||
|
||||
static void mxsfb_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
struct mxsfb_drm_private *mxsfb = dev->dev_private;
|
||||
|
||||
mxsfb_irq_disable(dev);
|
||||
free_irq(mxsfb->irq, dev);
|
||||
}
|
||||
|
||||
static int mxsfb_load(struct drm_device *drm,
|
||||
const struct mxsfb_devdata *devdata)
|
||||
{
|
||||
|
@ -226,8 +268,13 @@ static int mxsfb_load(struct drm_device *drm,
|
|||
|
||||
drm_mode_config_reset(drm);
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
goto err_vblank;
|
||||
mxsfb->irq = ret;
|
||||
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
|
||||
ret = mxsfb_irq_install(drm, mxsfb->irq);
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
|
||||
if (ret < 0) {
|
||||
|
@ -255,7 +302,7 @@ static void mxsfb_unload(struct drm_device *drm)
|
|||
drm_mode_config_cleanup(drm);
|
||||
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
drm_irq_uninstall(drm);
|
||||
mxsfb_irq_uninstall(drm);
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
|
||||
drm->dev_private = NULL;
|
||||
|
@ -263,38 +310,10 @@ static void mxsfb_unload(struct drm_device *drm)
|
|||
pm_runtime_disable(drm->dev);
|
||||
}
|
||||
|
||||
static void mxsfb_irq_disable(struct drm_device *drm)
|
||||
{
|
||||
struct mxsfb_drm_private *mxsfb = drm->dev_private;
|
||||
|
||||
mxsfb_enable_axi_clk(mxsfb);
|
||||
mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc);
|
||||
mxsfb_disable_axi_clk(mxsfb);
|
||||
}
|
||||
|
||||
static irqreturn_t mxsfb_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct drm_device *drm = data;
|
||||
struct mxsfb_drm_private *mxsfb = drm->dev_private;
|
||||
u32 reg;
|
||||
|
||||
reg = readl(mxsfb->base + LCDC_CTRL1);
|
||||
|
||||
if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
|
||||
drm_crtc_handle_vblank(&mxsfb->crtc);
|
||||
|
||||
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(fops);
|
||||
|
||||
static const struct drm_driver mxsfb_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.irq_handler = mxsfb_irq_handler,
|
||||
.irq_preinstall = mxsfb_irq_disable,
|
||||
.irq_uninstall = mxsfb_irq_disable,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
.fops = &fops,
|
||||
.name = "mxsfb-drm",
|
||||
|
|
|
@ -33,6 +33,8 @@ struct mxsfb_drm_private {
|
|||
struct clk *clk_axi;
|
||||
struct clk *clk_disp_axi;
|
||||
|
||||
unsigned int irq;
|
||||
|
||||
struct drm_device *drm;
|
||||
struct {
|
||||
struct drm_plane primary;
|
||||
|
|
|
@ -1659,23 +1659,27 @@ static void
|
|||
nv50_sor_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *state)
|
||||
{
|
||||
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
|
||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);
|
||||
struct nouveau_connector *nv_connector = nv50_outp_get_old_connector(state, nv_encoder);
|
||||
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
|
||||
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
|
||||
struct nouveau_backlight *backlight = nv_connector->backlight;
|
||||
#endif
|
||||
struct drm_dp_aux *aux = &nv_connector->aux;
|
||||
int ret;
|
||||
u8 pwr;
|
||||
|
||||
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
|
||||
if (backlight && backlight->uses_dpcd) {
|
||||
ret = drm_edp_backlight_disable(aux, &backlight->edp_info);
|
||||
if (ret < 0)
|
||||
NV_ERROR(drm, "Failed to disable backlight on [CONNECTOR:%d:%s]: %d\n",
|
||||
nv_connector->base.base.id, nv_connector->base.name, ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
|
||||
int ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &pwr);
|
||||
ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &pwr);
|
||||
|
||||
if (ret == 0) {
|
||||
pwr &= ~DP_SET_POWER_MASK;
|
||||
|
|
|
@ -3126,6 +3126,38 @@ static const struct panel_desc logictechno_lt170410_2whc = {
|
|||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode logictechno_lttd800480070_l6wh_rt_mode = {
|
||||
.clock = 33000,
|
||||
.hdisplay = 800,
|
||||
.hsync_start = 800 + 154,
|
||||
.hsync_end = 800 + 154 + 3,
|
||||
.htotal = 800 + 154 + 3 + 43,
|
||||
.vdisplay = 480,
|
||||
.vsync_start = 480 + 47,
|
||||
.vsync_end = 480 + 47 + 3,
|
||||
.vtotal = 480 + 47 + 3 + 20,
|
||||
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
||||
};
|
||||
|
||||
static const struct panel_desc logictechno_lttd800480070_l6wh_rt = {
|
||||
.modes = &logictechno_lttd800480070_l6wh_rt_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 154,
|
||||
.height = 86,
|
||||
},
|
||||
.delay = {
|
||||
.prepare = 45,
|
||||
.enable = 100,
|
||||
.disable = 100,
|
||||
.unprepare = 45
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE,
|
||||
.connector_type = DRM_MODE_CONNECTOR_DPI,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
|
||||
.clock = 30400,
|
||||
.hdisplay = 800,
|
||||
|
@ -3192,6 +3224,37 @@ static const struct panel_desc mitsubishi_aa070mc01 = {
|
|||
.bus_flags = DRM_BUS_FLAG_DE_HIGH,
|
||||
};
|
||||
|
||||
static const struct display_timing multi_inno_mi1010ait_1cp_timing = {
|
||||
.pixelclock = { 68900000, 70000000, 73400000 },
|
||||
.hactive = { 1280, 1280, 1280 },
|
||||
.hfront_porch = { 30, 60, 71 },
|
||||
.hback_porch = { 30, 60, 71 },
|
||||
.hsync_len = { 10, 10, 48 },
|
||||
.vactive = { 800, 800, 800 },
|
||||
.vfront_porch = { 5, 10, 10 },
|
||||
.vback_porch = { 5, 10, 10 },
|
||||
.vsync_len = { 5, 6, 13 },
|
||||
.flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
|
||||
DISPLAY_FLAGS_DE_HIGH,
|
||||
};
|
||||
|
||||
static const struct panel_desc multi_inno_mi1010ait_1cp = {
|
||||
.timings = &multi_inno_mi1010ait_1cp_timing,
|
||||
.num_timings = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 217,
|
||||
.height = 136,
|
||||
},
|
||||
.delay = {
|
||||
.enable = 50,
|
||||
.disable = 50,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH,
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct display_timing nec_nl12880bc20_05_timing = {
|
||||
.pixelclock = { 67000000, 71000000, 75000000 },
|
||||
.hactive = { 1280, 1280, 1280 },
|
||||
|
@ -4675,9 +4738,15 @@ static const struct of_device_id platform_of_match[] = {
|
|||
}, {
|
||||
.compatible = "logictechno,lt170410-2whc",
|
||||
.data = &logictechno_lt170410_2whc,
|
||||
}, {
|
||||
.compatible = "logictechno,lttd800480070-l6wh-rt",
|
||||
.data = &logictechno_lttd800480070_l6wh_rt,
|
||||
}, {
|
||||
.compatible = "mitsubishi,aa070mc01-ca1",
|
||||
.data = &mitsubishi_aa070mc01,
|
||||
}, {
|
||||
.compatible = "multi-inno,mi1010ait-1cp",
|
||||
.data = &multi_inno_mi1010ait_1cp,
|
||||
}, {
|
||||
.compatible = "nec,nl12880bc20-05",
|
||||
.data = &nec_nl12880bc20_05,
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_legacy.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/r128_drm.h>
|
||||
|
@ -603,7 +602,7 @@ int r128_do_cleanup_cce(struct drm_device *dev)
|
|||
* is freed, it's too late.
|
||||
*/
|
||||
if (dev->irq_enabled)
|
||||
drm_irq_uninstall(dev);
|
||||
drm_legacy_irq_uninstall(dev);
|
||||
|
||||
if (dev->dev_private) {
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
|
|
|
@ -607,10 +607,6 @@ static const struct drm_driver kms_driver = {
|
|||
.postclose = radeon_driver_postclose_kms,
|
||||
.lastclose = radeon_driver_lastclose_kms,
|
||||
.unload = radeon_driver_unload_kms,
|
||||
.irq_preinstall = radeon_driver_irq_preinstall_kms,
|
||||
.irq_postinstall = radeon_driver_irq_postinstall_kms,
|
||||
.irq_uninstall = radeon_driver_irq_uninstall_kms,
|
||||
.irq_handler = radeon_driver_irq_handler_kms,
|
||||
.ioctls = radeon_ioctls_kms,
|
||||
.num_ioctls = ARRAY_SIZE(radeon_ioctls_kms),
|
||||
.dumb_create = radeon_mode_dumb_create,
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/radeon_drm.h>
|
||||
|
@ -51,7 +51,7 @@
|
|||
* radeon_irq_process is a macro that points to the per-asic
|
||||
* irq handler callback.
|
||||
*/
|
||||
irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg)
|
||||
static irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
@ -118,7 +118,7 @@ static void radeon_dp_work_func(struct work_struct *work)
|
|||
* Gets the hw ready to enable irqs (all asics).
|
||||
* This function disables all interrupt sources on the GPU.
|
||||
*/
|
||||
void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
|
||||
static void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
|
@ -150,7 +150,7 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
|
|||
* Handles stuff to be done after enabling irqs (all asics).
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
|
||||
static int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
|
@ -169,7 +169,7 @@ int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
|
|||
*
|
||||
* This function disables all interrupt sources on the GPU (all asics).
|
||||
*/
|
||||
void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
|
||||
static void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
|
@ -194,6 +194,36 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
|
|||
spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
|
||||
}
|
||||
|
||||
static int radeon_irq_install(struct radeon_device *rdev, int irq)
|
||||
{
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
int ret;
|
||||
|
||||
if (irq == IRQ_NOTCONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
radeon_driver_irq_preinstall_kms(dev);
|
||||
|
||||
/* PCI devices require shared interrupts. */
|
||||
ret = request_irq(irq, radeon_driver_irq_handler_kms,
|
||||
IRQF_SHARED, dev->driver->name, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
radeon_driver_irq_postinstall_kms(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void radeon_irq_uninstall(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
||||
|
||||
radeon_driver_irq_uninstall_kms(dev);
|
||||
free_irq(pdev->irq, dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* radeon_msi_ok - asic specific msi checks
|
||||
*
|
||||
|
@ -314,7 +344,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
|
|||
INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
|
||||
|
||||
rdev->irq.installed = true;
|
||||
r = drm_irq_install(rdev->ddev, rdev->pdev->irq);
|
||||
r = radeon_irq_install(rdev, rdev->pdev->irq);
|
||||
if (r) {
|
||||
rdev->irq.installed = false;
|
||||
flush_delayed_work(&rdev->hotplug_work);
|
||||
|
@ -335,7 +365,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
|
|||
void radeon_irq_kms_fini(struct radeon_device *rdev)
|
||||
{
|
||||
if (rdev->irq.installed) {
|
||||
drm_irq_uninstall(rdev->ddev);
|
||||
radeon_irq_uninstall(rdev);
|
||||
rdev->irq.installed = false;
|
||||
if (rdev->msi_enabled)
|
||||
pci_disable_msi(rdev->pdev);
|
||||
|
|
|
@ -31,9 +31,5 @@
|
|||
u32 radeon_get_vblank_counter_kms(struct drm_crtc *crtc);
|
||||
int radeon_enable_vblank_kms(struct drm_crtc *crtc);
|
||||
void radeon_disable_vblank_kms(struct drm_crtc *crtc);
|
||||
irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg);
|
||||
void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
|
||||
int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
|
||||
void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
|
||||
|
||||
#endif /* __RADEON_KMS_H__ */
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
|
@ -118,11 +117,6 @@ static const struct drm_driver tidss_driver = {
|
|||
.date = "20180215",
|
||||
.major = 1,
|
||||
.minor = 0,
|
||||
|
||||
.irq_preinstall = tidss_irq_preinstall,
|
||||
.irq_postinstall = tidss_irq_postinstall,
|
||||
.irq_handler = tidss_irq_handler,
|
||||
.irq_uninstall = tidss_irq_uninstall,
|
||||
};
|
||||
|
||||
static int tidss_probe(struct platform_device *pdev)
|
||||
|
@ -172,10 +166,11 @@ static int tidss_probe(struct platform_device *pdev)
|
|||
ret = irq;
|
||||
goto err_runtime_suspend;
|
||||
}
|
||||
tidss->irq = irq;
|
||||
|
||||
ret = drm_irq_install(ddev, irq);
|
||||
ret = tidss_irq_install(ddev, irq);
|
||||
if (ret) {
|
||||
dev_err(dev, "drm_irq_install failed: %d\n", ret);
|
||||
dev_err(dev, "tidss_irq_install failed: %d\n", ret);
|
||||
goto err_runtime_suspend;
|
||||
}
|
||||
|
||||
|
@ -196,7 +191,7 @@ static int tidss_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_irq_uninstall:
|
||||
drm_irq_uninstall(ddev);
|
||||
tidss_irq_uninstall(ddev);
|
||||
|
||||
err_runtime_suspend:
|
||||
#ifndef CONFIG_PM
|
||||
|
@ -219,7 +214,7 @@ static int tidss_remove(struct platform_device *pdev)
|
|||
|
||||
drm_atomic_helper_shutdown(ddev);
|
||||
|
||||
drm_irq_uninstall(ddev);
|
||||
tidss_irq_uninstall(ddev);
|
||||
|
||||
#ifndef CONFIG_PM
|
||||
/* If we don't have PM, we need to call suspend manually */
|
||||
|
|
|
@ -27,6 +27,8 @@ struct tidss_device {
|
|||
unsigned int num_planes;
|
||||
struct drm_plane *planes[TIDSS_MAX_PLANES];
|
||||
|
||||
unsigned int irq;
|
||||
|
||||
spinlock_t wait_lock; /* protects the irq masks */
|
||||
dispc_irq_t irq_mask; /* enabled irqs in addition to wait_list */
|
||||
};
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "tidss_crtc.h"
|
||||
|
@ -50,7 +53,7 @@ void tidss_irq_disable_vblank(struct drm_crtc *crtc)
|
|||
spin_unlock_irqrestore(&tidss->wait_lock, flags);
|
||||
}
|
||||
|
||||
irqreturn_t tidss_irq_handler(int irq, void *arg)
|
||||
static irqreturn_t tidss_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *ddev = (struct drm_device *)arg;
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
|
@ -90,7 +93,7 @@ void tidss_irq_resume(struct tidss_device *tidss)
|
|||
spin_unlock_irqrestore(&tidss->wait_lock, flags);
|
||||
}
|
||||
|
||||
void tidss_irq_preinstall(struct drm_device *ddev)
|
||||
static void tidss_irq_preinstall(struct drm_device *ddev)
|
||||
{
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
|
||||
|
@ -104,7 +107,7 @@ void tidss_irq_preinstall(struct drm_device *ddev)
|
|||
tidss_runtime_put(tidss);
|
||||
}
|
||||
|
||||
int tidss_irq_postinstall(struct drm_device *ddev)
|
||||
static void tidss_irq_postinstall(struct drm_device *ddev)
|
||||
{
|
||||
struct tidss_device *tidss = to_tidss(ddev);
|
||||
unsigned long flags;
|
||||
|
@ -129,6 +132,22 @@ int tidss_irq_postinstall(struct drm_device *ddev)
|
|||
spin_unlock_irqrestore(&tidss->wait_lock, flags);
|
||||
|
||||
tidss_runtime_put(tidss);
|
||||
}
|
||||
|
||||
int tidss_irq_install(struct drm_device *ddev, unsigned int irq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (irq == IRQ_NOTCONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
tidss_irq_preinstall(ddev);
|
||||
|
||||
ret = request_irq(irq, tidss_irq_handler, 0, ddev->driver->name, ddev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tidss_irq_postinstall(ddev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -140,4 +159,6 @@ void tidss_irq_uninstall(struct drm_device *ddev)
|
|||
tidss_runtime_get(tidss);
|
||||
dispc_set_irqenable(tidss->dispc, 0);
|
||||
tidss_runtime_put(tidss);
|
||||
|
||||
free_irq(tidss->irq, ddev);
|
||||
}
|
||||
|
|
|
@ -67,10 +67,8 @@ struct tidss_device;
|
|||
void tidss_irq_enable_vblank(struct drm_crtc *crtc);
|
||||
void tidss_irq_disable_vblank(struct drm_crtc *crtc);
|
||||
|
||||
void tidss_irq_preinstall(struct drm_device *ddev);
|
||||
int tidss_irq_postinstall(struct drm_device *ddev);
|
||||
int tidss_irq_install(struct drm_device *ddev, unsigned int irq);
|
||||
void tidss_irq_uninstall(struct drm_device *ddev);
|
||||
irqreturn_t tidss_irq_handler(int irq, void *arg);
|
||||
|
||||
void tidss_irq_resume(struct tidss_device *tidss);
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_mm.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
@ -124,6 +123,39 @@ static int cpufreq_transition(struct notifier_block *nb,
|
|||
}
|
||||
#endif
|
||||
|
||||
static irqreturn_t tilcdc_irq(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = arg;
|
||||
struct tilcdc_drm_private *priv = dev->dev_private;
|
||||
|
||||
return tilcdc_crtc_irq(priv->crtc);
|
||||
}
|
||||
|
||||
static int tilcdc_irq_install(struct drm_device *dev, unsigned int irq)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = request_irq(irq, tilcdc_irq, 0, dev->driver->name, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->irq_enabled = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tilcdc_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = dev->dev_private;
|
||||
|
||||
if (!priv->irq_enabled)
|
||||
return;
|
||||
|
||||
free_irq(priv->irq, dev);
|
||||
priv->irq_enabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* DRM operations:
|
||||
*/
|
||||
|
@ -145,7 +177,7 @@ static void tilcdc_fini(struct drm_device *dev)
|
|||
drm_dev_unregister(dev);
|
||||
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
drm_irq_uninstall(dev);
|
||||
tilcdc_irq_uninstall(dev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
|
||||
if (priv->clk)
|
||||
|
@ -336,7 +368,12 @@ static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev)
|
|||
goto init_failed;
|
||||
}
|
||||
|
||||
ret = drm_irq_install(ddev, platform_get_irq(pdev, 0));
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
goto init_failed;
|
||||
priv->irq = ret;
|
||||
|
||||
ret = tilcdc_irq_install(ddev, priv->irq);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to install IRQ handler\n");
|
||||
goto init_failed;
|
||||
|
@ -360,13 +397,6 @@ init_failed:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t tilcdc_irq(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = arg;
|
||||
struct tilcdc_drm_private *priv = dev->dev_private;
|
||||
return tilcdc_crtc_irq(priv->crtc);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
static const struct {
|
||||
const char *name;
|
||||
|
@ -454,7 +484,6 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
|
|||
|
||||
static const struct drm_driver tilcdc_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.irq_handler = tilcdc_irq,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.debugfs_init = tilcdc_debugfs_init,
|
||||
|
|
|
@ -46,6 +46,8 @@ struct tilcdc_drm_private {
|
|||
struct clk *clk; /* functional clock */
|
||||
int rev; /* IP revision */
|
||||
|
||||
unsigned int irq;
|
||||
|
||||
/* don't attempt resolutions w/ higher W * H * Hz: */
|
||||
uint32_t max_bandwidth;
|
||||
/*
|
||||
|
@ -82,6 +84,7 @@ struct tilcdc_drm_private {
|
|||
|
||||
bool is_registered;
|
||||
bool is_componentized;
|
||||
bool irq_enabled;
|
||||
};
|
||||
|
||||
/* Sub-module for display. Since we don't know at compile time what panels
|
||||
|
|
|
@ -435,7 +435,7 @@ static void cirrus_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
|
||||
|
||||
cirrus_mode_set(cirrus, &crtc_state->mode, plane_state->fb);
|
||||
cirrus_fb_blit_fullscreen(plane_state->fb, &shadow_plane_state->map[0]);
|
||||
cirrus_fb_blit_fullscreen(plane_state->fb, &shadow_plane_state->data[0]);
|
||||
}
|
||||
|
||||
static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
|
||||
|
@ -451,7 +451,7 @@ static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
|
|||
cirrus_mode_set(cirrus, &crtc->mode, state->fb);
|
||||
|
||||
if (drm_atomic_helper_damage_merged(old_state, state, &rect))
|
||||
cirrus_fb_blit_rect(state->fb, &shadow_plane_state->map[0], &rect);
|
||||
cirrus_fb_blit_rect(state->fb, &shadow_plane_state->data[0], &rect);
|
||||
}
|
||||
|
||||
static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = {
|
||||
|
|
|
@ -554,7 +554,7 @@ static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
|
||||
|
||||
gm12u320->fb_update.draw_status_timeout = FIRST_FRAME_TIMEOUT;
|
||||
gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->map[0], &rect);
|
||||
gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->data[0], &rect);
|
||||
}
|
||||
|
||||
static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe)
|
||||
|
@ -572,7 +572,7 @@ static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe,
|
|||
struct drm_rect rect;
|
||||
|
||||
if (drm_atomic_helper_damage_merged(old_state, state, &rect))
|
||||
gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->map[0], &rect);
|
||||
gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->data[0], &rect);
|
||||
}
|
||||
|
||||
static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = {
|
||||
|
|
|
@ -639,7 +639,7 @@ simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||
struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
|
||||
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
|
||||
struct drm_framebuffer *fb = plane_state->fb;
|
||||
void *vmap = shadow_plane_state->map[0].vaddr; /* TODO: Use mapping abstraction properly */
|
||||
void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */
|
||||
struct drm_device *dev = &sdev->dev;
|
||||
int idx;
|
||||
|
||||
|
@ -677,7 +677,7 @@ simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
|
|||
struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
|
||||
struct drm_plane_state *plane_state = pipe->plane.state;
|
||||
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
|
||||
void *vmap = shadow_plane_state->map[0].vaddr; /* TODO: Use mapping abstraction properly */
|
||||
void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */
|
||||
struct drm_framebuffer *fb = plane_state->fb;
|
||||
struct drm_device *dev = &sdev->dev;
|
||||
struct drm_rect clip;
|
||||
|
|
|
@ -379,7 +379,7 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||
|
||||
udl->mode_buf_len = wrptr - buf;
|
||||
|
||||
udl_handle_damage(fb, &shadow_plane_state->map[0], 0, 0, fb->width, fb->height);
|
||||
udl_handle_damage(fb, &shadow_plane_state->data[0], 0, 0, fb->width, fb->height);
|
||||
|
||||
if (!crtc_state->mode_changed)
|
||||
return;
|
||||
|
@ -422,7 +422,7 @@ udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
|
|||
return;
|
||||
|
||||
if (drm_atomic_helper_damage_merged(old_plane_state, state, &rect))
|
||||
udl_handle_damage(fb, &shadow_plane_state->map[0], rect.x1, rect.y1,
|
||||
udl_handle_damage(fb, &shadow_plane_state->data[0], rect.x1, rect.y1,
|
||||
rect.x2 - rect.x1, rect.y2 - rect.y1);
|
||||
}
|
||||
|
||||
|
|
|
@ -398,7 +398,7 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane,
|
|||
u32 height = new_state->crtc_h;
|
||||
struct drm_shadow_plane_state *shadow_plane_state =
|
||||
to_drm_shadow_plane_state(new_state);
|
||||
struct dma_buf_map map = shadow_plane_state->map[0];
|
||||
struct dma_buf_map map = shadow_plane_state->data[0];
|
||||
u8 *src = map.vaddr; /* TODO: Use mapping abstraction properly */
|
||||
size_t data_size, mask_size;
|
||||
u32 flags;
|
||||
|
|
|
@ -168,10 +168,6 @@ static struct drm_driver vc4_drm_driver = {
|
|||
DRIVER_SYNCOBJ),
|
||||
.open = vc4_open,
|
||||
.postclose = vc4_close,
|
||||
.irq_handler = vc4_irq,
|
||||
.irq_preinstall = vc4_irq_preinstall,
|
||||
.irq_postinstall = vc4_irq_postinstall,
|
||||
.irq_uninstall = vc4_irq_uninstall,
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
.debugfs_init = vc4_debugfs_init,
|
||||
|
|
|
@ -74,6 +74,8 @@ struct vc4_perfmon {
|
|||
struct vc4_dev {
|
||||
struct drm_device base;
|
||||
|
||||
unsigned int irq;
|
||||
|
||||
struct vc4_hvs *hvs;
|
||||
struct vc4_v3d *v3d;
|
||||
struct vc4_dpi *dpi;
|
||||
|
@ -895,9 +897,9 @@ extern struct platform_driver vc4_vec_driver;
|
|||
extern struct platform_driver vc4_txp_driver;
|
||||
|
||||
/* vc4_irq.c */
|
||||
irqreturn_t vc4_irq(int irq, void *arg);
|
||||
void vc4_irq_preinstall(struct drm_device *dev);
|
||||
int vc4_irq_postinstall(struct drm_device *dev);
|
||||
void vc4_irq_enable(struct drm_device *dev);
|
||||
void vc4_irq_disable(struct drm_device *dev);
|
||||
int vc4_irq_install(struct drm_device *dev, int irq);
|
||||
void vc4_irq_uninstall(struct drm_device *dev);
|
||||
void vc4_irq_reset(struct drm_device *dev);
|
||||
|
||||
|
|
|
@ -45,6 +45,10 @@
|
|||
* current job can make progress.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include "vc4_drv.h"
|
||||
#include "vc4_regs.h"
|
||||
|
||||
|
@ -192,7 +196,7 @@ vc4_irq_finish_render_job(struct drm_device *dev)
|
|||
schedule_work(&vc4->job_done_work);
|
||||
}
|
||||
|
||||
irqreturn_t
|
||||
static irqreturn_t
|
||||
vc4_irq(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = arg;
|
||||
|
@ -234,8 +238,8 @@ vc4_irq(int irq, void *arg)
|
|||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
vc4_irq_preinstall(struct drm_device *dev)
|
||||
static void
|
||||
vc4_irq_prepare(struct drm_device *dev)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
|
||||
|
@ -251,24 +255,22 @@ vc4_irq_preinstall(struct drm_device *dev)
|
|||
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
|
||||
}
|
||||
|
||||
int
|
||||
vc4_irq_postinstall(struct drm_device *dev)
|
||||
void
|
||||
vc4_irq_enable(struct drm_device *dev)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
|
||||
if (!vc4->v3d)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/* Enable the render done interrupts. The out-of-memory interrupt is
|
||||
* enabled as soon as we have a binner BO allocated.
|
||||
*/
|
||||
V3D_WRITE(V3D_INTENA, V3D_INT_FLDONE | V3D_INT_FRDONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
vc4_irq_uninstall(struct drm_device *dev)
|
||||
vc4_irq_disable(struct drm_device *dev)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
|
||||
|
@ -282,11 +284,37 @@ vc4_irq_uninstall(struct drm_device *dev)
|
|||
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
|
||||
|
||||
/* Finish any interrupt handler still in flight. */
|
||||
disable_irq(dev->irq);
|
||||
disable_irq(vc4->irq);
|
||||
|
||||
cancel_work_sync(&vc4->overflow_mem_work);
|
||||
}
|
||||
|
||||
int vc4_irq_install(struct drm_device *dev, int irq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (irq == IRQ_NOTCONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
vc4_irq_prepare(dev);
|
||||
|
||||
ret = request_irq(irq, vc4_irq, 0, dev->driver->name, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vc4_irq_enable(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vc4_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
|
||||
vc4_irq_disable(dev);
|
||||
free_irq(vc4->irq, dev);
|
||||
}
|
||||
|
||||
/** Reinitializes interrupt registers when a GPU reset is performed. */
|
||||
void vc4_irq_reset(struct drm_device *dev)
|
||||
{
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <drm/drm_irq.h>
|
||||
|
||||
#include "vc4_drv.h"
|
||||
#include "vc4_regs.h"
|
||||
|
||||
|
@ -361,7 +359,7 @@ static int vc4_v3d_runtime_suspend(struct device *dev)
|
|||
struct vc4_v3d *v3d = dev_get_drvdata(dev);
|
||||
struct vc4_dev *vc4 = v3d->vc4;
|
||||
|
||||
vc4_irq_uninstall(&vc4->base);
|
||||
vc4_irq_disable(&vc4->base);
|
||||
|
||||
clk_disable_unprepare(v3d->clk);
|
||||
|
||||
|
@ -381,8 +379,8 @@ static int vc4_v3d_runtime_resume(struct device *dev)
|
|||
vc4_v3d_init_hw(&vc4->base);
|
||||
|
||||
/* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */
|
||||
enable_irq(vc4->base.irq);
|
||||
vc4_irq_postinstall(&vc4->base);
|
||||
enable_irq(vc4->irq);
|
||||
vc4_irq_enable(&vc4->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -448,7 +446,12 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
|
|||
|
||||
vc4_v3d_init_hw(drm);
|
||||
|
||||
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
vc4->irq = ret;
|
||||
|
||||
ret = vc4_irq_install(drm, vc4->irq);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to install IRQ handler\n");
|
||||
return ret;
|
||||
|
@ -473,7 +476,7 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master,
|
|||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
drm_irq_uninstall(drm);
|
||||
vc4_irq_uninstall(drm);
|
||||
|
||||
/* Disable the binner's overflow memory address, so the next
|
||||
* driver probe (if any) doesn't try to reuse our old
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/via_drm.h>
|
||||
|
||||
#include "via_drv.h"
|
||||
|
@ -86,7 +85,7 @@ int via_final_context(struct drm_device *dev, int context)
|
|||
/* Last context, perform cleanup */
|
||||
if (list_is_singular(&dev->ctxlist)) {
|
||||
DRM_DEBUG("Last Context\n");
|
||||
drm_irq_uninstall(dev);
|
||||
drm_legacy_irq_uninstall(dev);
|
||||
via_cleanup_futex(dev_priv);
|
||||
via_do_cleanup_map(dev);
|
||||
}
|
||||
|
|
|
@ -98,6 +98,8 @@ struct dma_buf *virtgpu_gem_prime_export(struct drm_gem_object *obj,
|
|||
} else {
|
||||
bo->uuid_state = STATE_ERR;
|
||||
}
|
||||
} else if (!(bo->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)) {
|
||||
bo->uuid_state = STATE_ERR;
|
||||
}
|
||||
|
||||
exp_info.ops = &virtgpu_dmabuf_ops.ops;
|
||||
|
|
|
@ -257,7 +257,7 @@ void vkms_composer_worker(struct work_struct *work)
|
|||
return;
|
||||
|
||||
if (wb_pending)
|
||||
vaddr_out = crtc_state->active_writeback->map[0].vaddr;
|
||||
vaddr_out = crtc_state->active_writeback->data[0].vaddr;
|
||||
|
||||
ret = compose_active_planes(&vaddr_out, primary_composer,
|
||||
crtc_state);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
struct vkms_writeback_job {
|
||||
struct dma_buf_map map[DRM_FORMAT_MAX_PLANES];
|
||||
struct dma_buf_map data[DRM_FORMAT_MAX_PLANES];
|
||||
};
|
||||
|
||||
struct vkms_composer {
|
||||
|
|
|
@ -111,7 +111,7 @@ static void vkms_plane_atomic_update(struct drm_plane *plane,
|
|||
memcpy(&composer->src, &new_state->src, sizeof(struct drm_rect));
|
||||
memcpy(&composer->dst, &new_state->dst, sizeof(struct drm_rect));
|
||||
memcpy(&composer->fb, fb, sizeof(struct drm_framebuffer));
|
||||
memcpy(&composer->map, &shadow_plane_state->map, sizeof(composer->map));
|
||||
memcpy(&composer->map, &shadow_plane_state->data, sizeof(composer->map));
|
||||
drm_framebuffer_get(&composer->fb);
|
||||
composer->offset = fb->offsets[0];
|
||||
composer->pitch = fb->pitches[0];
|
||||
|
|
|
@ -75,7 +75,7 @@ static int vkms_wb_prepare_job(struct drm_writeback_connector *wb_connector,
|
|||
if (!vkmsjob)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = drm_gem_fb_vmap(job->fb, vkmsjob->map);
|
||||
ret = drm_gem_fb_vmap(job->fb, vkmsjob->map, vkmsjob->data);
|
||||
if (ret) {
|
||||
DRM_ERROR("vmap failed: %d\n", ret);
|
||||
goto err_kfree;
|
||||
|
|
|
@ -97,19 +97,18 @@ typedef __attribute__((aligned(32))) struct MKSGuestStatInfoEntry {
|
|||
} MKSGuestStatInfoEntry;
|
||||
|
||||
#define INVALID_PPN64 ((PPN64)0x000fffffffffffffULL)
|
||||
#define vmw_num_pages(size) (PAGE_ALIGN(size) >> PAGE_SHIFT)
|
||||
|
||||
#define MKS_GUEST_STAT_INSTANCE_DESC_LENGTH 1024
|
||||
#define MKS_GUEST_STAT_INSTANCE_MAX_STATS 4096
|
||||
#define MKS_GUEST_STAT_INSTANCE_MAX_STAT_PPNS \
|
||||
(vmw_num_pages(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \
|
||||
#define MKS_GUEST_STAT_INSTANCE_MAX_STAT_PPNS \
|
||||
(PFN_UP(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \
|
||||
sizeof(MKSGuestStatCounterTime)))
|
||||
#define MKS_GUEST_STAT_INSTANCE_MAX_INFO_PPNS \
|
||||
(vmw_num_pages(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \
|
||||
#define MKS_GUEST_STAT_INSTANCE_MAX_INFO_PPNS \
|
||||
(PFN_UP(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \
|
||||
sizeof(MKSGuestStatInfoEntry)))
|
||||
#define MKS_GUEST_STAT_AVERAGE_NAME_LENGTH 40
|
||||
#define MKS_GUEST_STAT_INSTANCE_MAX_STRS_PPNS \
|
||||
(vmw_num_pages(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \
|
||||
#define MKS_GUEST_STAT_INSTANCE_MAX_STRS_PPNS \
|
||||
(PFN_UP(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \
|
||||
MKS_GUEST_STAT_AVERAGE_NAME_LENGTH))
|
||||
|
||||
/*
|
||||
|
|
|
@ -405,7 +405,7 @@ static size_t vmw_bo_acc_size(struct vmw_private *dev_priv, size_t size,
|
|||
bool user)
|
||||
{
|
||||
static size_t struct_size, user_struct_size;
|
||||
size_t num_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
|
||||
size_t num_pages = PFN_UP(size);
|
||||
size_t page_array_size = ttm_round_pot(num_pages * sizeof(void *));
|
||||
|
||||
if (unlikely(struct_size == 0)) {
|
||||
|
@ -474,7 +474,6 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size,
|
|||
struct ttm_placement *placement,
|
||||
struct ttm_buffer_object **p_bo)
|
||||
{
|
||||
unsigned npages = PAGE_ALIGN(size) >> PAGE_SHIFT;
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
struct ttm_buffer_object *bo;
|
||||
size_t acc_size;
|
||||
|
@ -485,7 +484,7 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size,
|
|||
return -ENOMEM;
|
||||
|
||||
acc_size = ttm_round_pot(sizeof(*bo));
|
||||
acc_size += ttm_round_pot(npages * sizeof(void *));
|
||||
acc_size += ttm_round_pot(PFN_UP(size) * sizeof(void *));
|
||||
acc_size += ttm_round_pot(sizeof(struct ttm_tt));
|
||||
|
||||
ret = ttm_mem_global_alloc(&ttm_mem_glob, acc_size, &ctx);
|
||||
|
|
|
@ -358,8 +358,7 @@ static void vmw_cmdbuf_ctx_submit(struct vmw_cmdbuf_man *man,
|
|||
break;
|
||||
}
|
||||
|
||||
list_del(&entry->list);
|
||||
list_add_tail(&entry->list, &ctx->hw_submitted);
|
||||
list_move_tail(&entry->list, &ctx->hw_submitted);
|
||||
ctx->num_hw_submitted++;
|
||||
}
|
||||
|
||||
|
@ -802,7 +801,7 @@ static int vmw_cmdbuf_alloc_space(struct vmw_cmdbuf_man *man,
|
|||
{
|
||||
struct vmw_cmdbuf_alloc_info info;
|
||||
|
||||
info.page_size = PAGE_ALIGN(size) >> PAGE_SHIFT;
|
||||
info.page_size = PFN_UP(size);
|
||||
info.node = node;
|
||||
info.done = false;
|
||||
|
||||
|
|
|
@ -169,8 +169,7 @@ void vmw_cmdbuf_res_revert(struct list_head *list)
|
|||
case VMW_CMDBUF_RES_DEL:
|
||||
ret = drm_ht_insert_item(&entry->man->resources, &entry->hash);
|
||||
BUG_ON(ret);
|
||||
list_del(&entry->head);
|
||||
list_add_tail(&entry->head, &entry->man->list);
|
||||
list_move_tail(&entry->head, &entry->man->list);
|
||||
entry->state = VMW_CMDBUF_RES_COMMITTED;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -607,8 +607,7 @@ struct vmw_resource *vmw_cotable_alloc(struct vmw_private *dev_priv,
|
|||
if (num_entries < co_info[type].min_initial_entries) {
|
||||
vcotbl->res.backup_size = co_info[type].min_initial_entries *
|
||||
co_info[type].size;
|
||||
vcotbl->res.backup_size =
|
||||
(vcotbl->res.backup_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
vcotbl->res.backup_size = PFN_ALIGN(vcotbl->res.backup_size);
|
||||
}
|
||||
|
||||
vcotbl->scrubbed = true;
|
||||
|
|
|
@ -1295,7 +1295,6 @@ extern struct vmw_cmdbuf_res_manager *
|
|||
vmw_context_res_man(struct vmw_resource *ctx);
|
||||
extern struct vmw_resource *vmw_context_cotable(struct vmw_resource *ctx,
|
||||
SVGACOTableType cotable_type);
|
||||
extern struct list_head *vmw_context_binding_list(struct vmw_resource *ctx);
|
||||
struct vmw_ctx_binding_state;
|
||||
extern struct vmw_ctx_binding_state *
|
||||
vmw_context_binding_state(struct vmw_resource *ctx);
|
||||
|
|
|
@ -100,7 +100,7 @@ static int vmw_cursor_update_bo(struct vmw_private *dev_priv,
|
|||
int ret;
|
||||
|
||||
kmap_offset = 0;
|
||||
kmap_num = (width*height*4 + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
kmap_num = PFN_UP(width*height*4);
|
||||
|
||||
ret = ttm_bo_reserve(&bo->base, true, false, NULL);
|
||||
if (unlikely(ret != 0)) {
|
||||
|
|
|
@ -256,8 +256,7 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv,
|
|||
if (!otables[i].enabled)
|
||||
continue;
|
||||
|
||||
otables[i].size =
|
||||
(otables[i].size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
otables[i].size = PFN_ALIGN(otables[i].size);
|
||||
bo_size += otables[i].size;
|
||||
}
|
||||
|
||||
|
@ -385,7 +384,7 @@ static unsigned long vmw_mob_calculate_pt_pages(unsigned long data_pages)
|
|||
while (likely(data_size > PAGE_SIZE)) {
|
||||
data_size = DIV_ROUND_UP(data_size, PAGE_SIZE);
|
||||
data_size *= VMW_PPN_SIZE;
|
||||
tot_size += (data_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
tot_size += PFN_ALIGN(data_size);
|
||||
}
|
||||
|
||||
return tot_size >> PAGE_SHIFT;
|
||||
|
|
|
@ -1016,9 +1016,9 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
struct page *page;
|
||||
MKSGuestStatInstanceDescriptor *pdesc;
|
||||
const size_t num_pages_stat = vmw_num_pages(arg->stat_len);
|
||||
const size_t num_pages_info = vmw_num_pages(arg->info_len);
|
||||
const size_t num_pages_strs = vmw_num_pages(arg->strs_len);
|
||||
const size_t num_pages_stat = PFN_UP(arg->stat_len);
|
||||
const size_t num_pages_info = PFN_UP(arg->info_len);
|
||||
const size_t num_pages_strs = PFN_UP(arg->strs_len);
|
||||
long desc_len;
|
||||
long nr_pinned_stat;
|
||||
long nr_pinned_info;
|
||||
|
|
|
@ -353,8 +353,7 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv,
|
|||
static int vmw_resource_buf_alloc(struct vmw_resource *res,
|
||||
bool interruptible)
|
||||
{
|
||||
unsigned long size =
|
||||
(res->backup_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
unsigned long size = PFN_ALIGN(res->backup_size);
|
||||
struct vmw_buffer_object *backup;
|
||||
int ret;
|
||||
|
||||
|
|
|
@ -981,8 +981,7 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv,
|
|||
goto no_reserve;
|
||||
|
||||
/* Map and copy shader bytecode. */
|
||||
ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT,
|
||||
&map);
|
||||
ret = ttm_bo_kmap(&buf->base, 0, PFN_UP(size), &map);
|
||||
if (unlikely(ret != 0)) {
|
||||
ttm_bo_unreserve(&buf->base);
|
||||
goto no_reserve;
|
||||
|
|
|
@ -865,7 +865,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
|
|||
user_srf->prime.base.shareable = false;
|
||||
user_srf->prime.base.tfile = NULL;
|
||||
if (drm_is_primary_client(file_priv))
|
||||
user_srf->master = drm_master_get(file_priv->master);
|
||||
user_srf->master = drm_file_get_master(file_priv);
|
||||
|
||||
/**
|
||||
* From this point, the generic resource management functions
|
||||
|
@ -1534,7 +1534,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
|
|||
|
||||
user_srf = container_of(srf, struct vmw_user_surface, srf);
|
||||
if (drm_is_primary_client(file_priv))
|
||||
user_srf->master = drm_master_get(file_priv->master);
|
||||
user_srf->master = drm_file_get_master(file_priv);
|
||||
|
||||
res = &user_srf->srf.res;
|
||||
|
||||
|
|
|
@ -191,20 +191,6 @@ struct drm_device {
|
|||
*/
|
||||
struct list_head clientlist;
|
||||
|
||||
/**
|
||||
* @irq_enabled:
|
||||
*
|
||||
* Indicates that interrupt handling is enabled, specifically vblank
|
||||
* handling. Drivers which don't use drm_irq_install() need to set this
|
||||
* to true manually.
|
||||
*/
|
||||
bool irq_enabled;
|
||||
|
||||
/**
|
||||
* @irq: Used by the drm_irq_install() and drm_irq_unistall() helpers.
|
||||
*/
|
||||
int irq;
|
||||
|
||||
/**
|
||||
* @vblank_disable_immediate:
|
||||
*
|
||||
|
@ -372,6 +358,10 @@ struct drm_device {
|
|||
|
||||
/* Scatter gather memory */
|
||||
struct drm_sg_mem *sg;
|
||||
|
||||
/* IRQs */
|
||||
bool irq_enabled;
|
||||
int irq;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -137,10 +137,6 @@ enum drm_driver_feature {
|
|||
* @DRIVER_HAVE_IRQ:
|
||||
*
|
||||
* Legacy irq support. Only for legacy drivers. Do not use.
|
||||
*
|
||||
* New drivers can either use the drm_irq_install() and
|
||||
* drm_irq_uninstall() helper functions, or roll their own irq support
|
||||
* code by calling request_irq() directly.
|
||||
*/
|
||||
DRIVER_HAVE_IRQ = BIT(30),
|
||||
/**
|
||||
|
@ -271,42 +267,6 @@ struct drm_driver {
|
|||
*/
|
||||
void (*release) (struct drm_device *);
|
||||
|
||||
/**
|
||||
* @irq_handler:
|
||||
*
|
||||
* Interrupt handler called when using drm_irq_install(). Not used by
|
||||
* drivers which implement their own interrupt handling.
|
||||
*/
|
||||
irqreturn_t(*irq_handler) (int irq, void *arg);
|
||||
|
||||
/**
|
||||
* @irq_preinstall:
|
||||
*
|
||||
* Optional callback used by drm_irq_install() which is called before
|
||||
* the interrupt handler is registered. This should be used to clear out
|
||||
* any pending interrupts (from e.g. firmware based drives) and reset
|
||||
* the interrupt handling registers.
|
||||
*/
|
||||
void (*irq_preinstall) (struct drm_device *dev);
|
||||
|
||||
/**
|
||||
* @irq_postinstall:
|
||||
*
|
||||
* Optional callback used by drm_irq_install() which is called after
|
||||
* the interrupt handler is registered. This should be used to enable
|
||||
* interrupt generation in the hardware.
|
||||
*/
|
||||
int (*irq_postinstall) (struct drm_device *dev);
|
||||
|
||||
/**
|
||||
* @irq_uninstall:
|
||||
*
|
||||
* Optional callback used by drm_irq_uninstall() which is called before
|
||||
* the interrupt handler is unregistered. This should be used to disable
|
||||
* interrupt generation in the hardware.
|
||||
*/
|
||||
void (*irq_uninstall) (struct drm_device *dev);
|
||||
|
||||
/**
|
||||
* @master_set:
|
||||
*
|
||||
|
@ -504,6 +464,10 @@ struct drm_driver {
|
|||
int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
int (*dma_quiescent) (struct drm_device *);
|
||||
int (*context_dtor) (struct drm_device *dev, int context);
|
||||
irqreturn_t (*irq_handler)(int irq, void *arg);
|
||||
void (*irq_preinstall)(struct drm_device *dev);
|
||||
int (*irq_postinstall)(struct drm_device *dev);
|
||||
void (*irq_uninstall)(struct drm_device *dev);
|
||||
u32 (*get_vblank_counter)(struct drm_device *dev, unsigned int pipe);
|
||||
int (*enable_vblank)(struct drm_device *dev, unsigned int pipe);
|
||||
void (*disable_vblank)(struct drm_device *dev, unsigned int pipe);
|
||||
|
|
|
@ -336,7 +336,7 @@ struct edid {
|
|||
u8 features;
|
||||
/* Color characteristics */
|
||||
u8 red_green_lo;
|
||||
u8 black_white_lo;
|
||||
u8 blue_white_lo;
|
||||
u8 red_x;
|
||||
u8 red_y;
|
||||
u8 green_x;
|
||||
|
|
|
@ -233,6 +233,10 @@ struct drm_file {
|
|||
* this only matches &drm_device.master if the master is the currently
|
||||
* active one.
|
||||
*
|
||||
* To update @master, both &drm_device.master_mutex and
|
||||
* @master_lookup_lock need to be held, therefore holding either of
|
||||
* them is safe and enough for the read side.
|
||||
*
|
||||
* When dereferencing this pointer, either hold struct
|
||||
* &drm_device.master_mutex for the duration of the pointer's use, or
|
||||
* use drm_file_get_master() if struct &drm_device.master_mutex is not
|
||||
|
|
|
@ -42,6 +42,14 @@ struct drm_shadow_plane_state {
|
|||
* prepare_fb callback and removed in the cleanup_fb callback.
|
||||
*/
|
||||
struct dma_buf_map map[DRM_FORMAT_MAX_PLANES];
|
||||
|
||||
/**
|
||||
* @data: Address of each framebuffer BO's data
|
||||
*
|
||||
* The address of the data stored in each mapping. This is different
|
||||
* for framebuffers with non-zero offset fields.
|
||||
*/
|
||||
struct dma_buf_map data[DRM_FORMAT_MAX_PLANES];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,7 +40,8 @@ drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
|
|||
const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
|
||||
int drm_gem_fb_vmap(struct drm_framebuffer *fb,
|
||||
struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES]);
|
||||
struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES],
|
||||
struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]);
|
||||
void drm_gem_fb_vunmap(struct drm_framebuffer *fb,
|
||||
struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES]);
|
||||
int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir);
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Intel Corp.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _DRM_IRQ_H_
|
||||
#define _DRM_IRQ_H_
|
||||
|
||||
struct drm_device;
|
||||
|
||||
int drm_irq_install(struct drm_device *dev, int irq);
|
||||
int drm_irq_uninstall(struct drm_device *dev);
|
||||
int devm_drm_irq_install(struct drm_device *dev, int irq);
|
||||
#endif
|
|
@ -192,6 +192,9 @@ do { \
|
|||
void drm_legacy_idlelock_take(struct drm_lock_data *lock);
|
||||
void drm_legacy_idlelock_release(struct drm_lock_data *lock);
|
||||
|
||||
/* drm_irq.c */
|
||||
int drm_legacy_irq_uninstall(struct drm_device *dev);
|
||||
|
||||
/* drm_pci.c */
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
|
|
@ -153,6 +153,33 @@ struct drm_simple_display_pipe_funcs {
|
|||
*/
|
||||
void (*disable_vblank)(struct drm_simple_display_pipe *pipe);
|
||||
|
||||
/**
|
||||
* @reset_crtc:
|
||||
*
|
||||
* Optional, called by &drm_crtc_funcs.reset. Please read the
|
||||
* documentation for the &drm_crtc_funcs.reset hook for more details.
|
||||
*/
|
||||
void (*reset_crtc)(struct drm_simple_display_pipe *pipe);
|
||||
|
||||
/**
|
||||
* @duplicate_crtc_state:
|
||||
*
|
||||
* Optional, called by &drm_crtc_funcs.atomic_duplicate_state. Please
|
||||
* read the documentation for the &drm_crtc_funcs.atomic_duplicate_state
|
||||
* hook for more details.
|
||||
*/
|
||||
struct drm_crtc_state * (*duplicate_crtc_state)(struct drm_simple_display_pipe *pipe);
|
||||
|
||||
/**
|
||||
* @destroy_crtc_state:
|
||||
*
|
||||
* Optional, called by &drm_crtc_funcs.atomic_destroy_state. Please
|
||||
* read the documentation for the &drm_crtc_funcs.atomic_destroy_state
|
||||
* hook for more details.
|
||||
*/
|
||||
void (*destroy_crtc_state)(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_crtc_state *crtc_state);
|
||||
|
||||
/**
|
||||
* @reset_plane:
|
||||
*
|
||||
|
|
|
@ -54,7 +54,7 @@ struct dma_buf_ops {
|
|||
* device), and otherwise need to fail the attach operation.
|
||||
*
|
||||
* The exporter should also in general check whether the current
|
||||
* allocation fullfills the DMA constraints of the new device. If this
|
||||
* allocation fulfills the DMA constraints of the new device. If this
|
||||
* is not the case, and the allocation cannot be moved, it should also
|
||||
* fail the attach operation.
|
||||
*
|
||||
|
@ -161,7 +161,7 @@ struct dma_buf_ops {
|
|||
*
|
||||
* Returns:
|
||||
*
|
||||
* A &sg_table scatter list of or the backing storage of the DMA buffer,
|
||||
* A &sg_table scatter list of the backing storage of the DMA buffer,
|
||||
* already mapped into the device address space of the &device attached
|
||||
* with the provided &dma_buf_attachment. The addresses and lengths in
|
||||
* the scatter list are PAGE_SIZE aligned.
|
||||
|
@ -183,7 +183,7 @@ struct dma_buf_ops {
|
|||
*
|
||||
* This is called by dma_buf_unmap_attachment() and should unmap and
|
||||
* release the &sg_table allocated in @map_dma_buf, and it is mandatory.
|
||||
* For static dma_buf handling this might also unpins the backing
|
||||
* For static dma_buf handling this might also unpin the backing
|
||||
* storage if this is the last mapping of the DMA buffer.
|
||||
*/
|
||||
void (*unmap_dma_buf)(struct dma_buf_attachment *,
|
||||
|
@ -252,7 +252,7 @@ struct dma_buf_ops {
|
|||
* This callback is used by the dma_buf_mmap() function
|
||||
*
|
||||
* Note that the mapping needs to be incoherent, userspace is expected
|
||||
* to braket CPU access using the DMA_BUF_IOCTL_SYNC interface.
|
||||
* to bracket CPU access using the DMA_BUF_IOCTL_SYNC interface.
|
||||
*
|
||||
* Because dma-buf buffers have invariant size over their lifetime, the
|
||||
* dma-buf core checks whether a vma is too large and rejects such
|
||||
|
@ -580,7 +580,7 @@ static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
|
|||
|
||||
/**
|
||||
* dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic
|
||||
* mappinsg
|
||||
* mappings
|
||||
* @attach: the DMA-buf attachment to check
|
||||
*
|
||||
* Returns true if a DMA-buf importer wants to call the map/unmap functions with
|
||||
|
|
|
@ -306,31 +306,29 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);
|
|||
|
||||
#define lockdep_depth(tsk) (debug_locks ? (tsk)->lockdep_depth : 0)
|
||||
|
||||
#define lockdep_assert_held(l) do { \
|
||||
WARN_ON(debug_locks && \
|
||||
lockdep_is_held(l) == LOCK_STATE_NOT_HELD); \
|
||||
} while (0)
|
||||
#define lockdep_assert(cond) \
|
||||
do { WARN_ON(debug_locks && !(cond)); } while (0)
|
||||
|
||||
#define lockdep_assert_not_held(l) do { \
|
||||
WARN_ON(debug_locks && \
|
||||
lockdep_is_held(l) == LOCK_STATE_HELD); \
|
||||
} while (0)
|
||||
#define lockdep_assert_once(cond) \
|
||||
do { WARN_ON_ONCE(debug_locks && !(cond)); } while (0)
|
||||
|
||||
#define lockdep_assert_held_write(l) do { \
|
||||
WARN_ON(debug_locks && !lockdep_is_held_type(l, 0)); \
|
||||
} while (0)
|
||||
#define lockdep_assert_held(l) \
|
||||
lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD)
|
||||
|
||||
#define lockdep_assert_held_read(l) do { \
|
||||
WARN_ON(debug_locks && !lockdep_is_held_type(l, 1)); \
|
||||
} while (0)
|
||||
#define lockdep_assert_not_held(l) \
|
||||
lockdep_assert(lockdep_is_held(l) != LOCK_STATE_HELD)
|
||||
|
||||
#define lockdep_assert_held_once(l) do { \
|
||||
WARN_ON_ONCE(debug_locks && !lockdep_is_held(l)); \
|
||||
} while (0)
|
||||
#define lockdep_assert_held_write(l) \
|
||||
lockdep_assert(lockdep_is_held_type(l, 0))
|
||||
|
||||
#define lockdep_assert_none_held_once() do { \
|
||||
WARN_ON_ONCE(debug_locks && current->lockdep_depth); \
|
||||
} while (0)
|
||||
#define lockdep_assert_held_read(l) \
|
||||
lockdep_assert(lockdep_is_held_type(l, 1))
|
||||
|
||||
#define lockdep_assert_held_once(l) \
|
||||
lockdep_assert_once(lockdep_is_held(l) != LOCK_STATE_NOT_HELD)
|
||||
|
||||
#define lockdep_assert_none_held_once() \
|
||||
lockdep_assert_once(!current->lockdep_depth)
|
||||
|
||||
#define lockdep_recursing(tsk) ((tsk)->lockdep_recursion)
|
||||
|
||||
|
@ -407,6 +405,9 @@ extern int lock_is_held(const void *);
|
|||
extern int lockdep_is_held(const void *);
|
||||
#define lockdep_is_held_type(l, r) (1)
|
||||
|
||||
#define lockdep_assert(c) do { } while (0)
|
||||
#define lockdep_assert_once(c) do { } while (0)
|
||||
|
||||
#define lockdep_assert_held(l) do { (void)(l); } while (0)
|
||||
#define lockdep_assert_not_held(l) do { (void)(l); } while (0)
|
||||
#define lockdep_assert_held_write(l) do { (void)(l); } while (0)
|
||||
|
|
Loading…
Add table
Reference in a new issue