Skip to content

Commit 83a956d

Browse files
committed
drm: xlnx: zynqmp_dpsub: Move CRTC handling to zynqmp_kms.c
Decouple the CRTC handling from the display controller programming by moving the corresponding code from zynqmp_disp.c to zynqmp_kms.c. This prepares for using the DPSUB with a live video input, without creating a DRM CRTC in the DPSUB driver. Signed-off-by: Laurent Pinchart <[email protected]>
1 parent 76c8eeb commit 83a956d

File tree

5 files changed

+232
-235
lines changed

5 files changed

+232
-235
lines changed

drivers/gpu/drm/xlnx/zynqmp_disp.c

Lines changed: 20 additions & 231 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,21 @@
1111

1212
#include <drm/drm_atomic.h>
1313
#include <drm/drm_atomic_helper.h>
14-
#include <drm/drm_atomic_uapi.h>
1514
#include <drm/drm_blend.h>
16-
#include <drm/drm_crtc.h>
1715
#include <drm/drm_device.h>
1816
#include <drm/drm_fb_dma_helper.h>
1917
#include <drm/drm_fourcc.h>
2018
#include <drm/drm_framebuffer.h>
2119
#include <drm/drm_managed.h>
2220
#include <drm/drm_plane.h>
23-
#include <drm/drm_vblank.h>
2421

2522
#include <linux/clk.h>
26-
#include <linux/delay.h>
2723
#include <linux/dma/xilinx_dpdma.h>
2824
#include <linux/dma-mapping.h>
2925
#include <linux/dmaengine.h>
3026
#include <linux/module.h>
3127
#include <linux/of.h>
3228
#include <linux/platform_device.h>
33-
#include <linux/pm_runtime.h>
34-
#include <linux/spinlock.h>
3529

3630
#include "zynqmp_disp.h"
3731
#include "zynqmp_disp_regs.h"
@@ -88,16 +82,6 @@ struct zynqmp_disp_format {
8882
const u32 *sf;
8983
};
9084

91-
/**
92-
* enum zynqmp_disp_layer_id - Layer identifier
93-
* @ZYNQMP_DISP_LAYER_VID: Video layer
94-
* @ZYNQMP_DISP_LAYER_GFX: Graphics layer
95-
*/
96-
enum zynqmp_disp_layer_id {
97-
ZYNQMP_DISP_LAYER_VID,
98-
ZYNQMP_DISP_LAYER_GFX
99-
};
100-
10185
/**
10286
* enum zynqmp_disp_layer_mode - Layer mode
10387
* @ZYNQMP_DISP_LAYER_NONLIVE: non-live (memory) mode
@@ -143,7 +127,7 @@ struct zynqmp_disp_layer_info {
143127
* @mode: Current operation mode
144128
*/
145129
struct zynqmp_disp_layer {
146-
enum zynqmp_disp_layer_id id;
130+
enum zynqmp_dpsub_layer_id id;
147131
struct zynqmp_disp *disp;
148132
const struct zynqmp_disp_layer_info *info;
149133

@@ -398,12 +382,12 @@ static void zynqmp_disp_avbuf_write(struct zynqmp_disp *disp, int reg, u32 val)
398382

399383
static bool zynqmp_disp_layer_is_gfx(const struct zynqmp_disp_layer *layer)
400384
{
401-
return layer->id == ZYNQMP_DISP_LAYER_GFX;
385+
return layer->id == ZYNQMP_DPSUB_LAYER_GFX;
402386
}
403387

404388
static bool zynqmp_disp_layer_is_video(const struct zynqmp_disp_layer *layer)
405389
{
406-
return layer->id == ZYNQMP_DISP_LAYER_VID;
390+
return layer->id == ZYNQMP_DPSUB_LAYER_VID;
407391
}
408392

409393
/**
@@ -882,35 +866,6 @@ static void zynqmp_disp_audio_disable(struct zynqmp_disp *disp)
882866
ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
883867
}
884868

885-
/* -----------------------------------------------------------------------------
886-
* ZynqMP Display external functions for zynqmp_dp
887-
*/
888-
889-
/**
890-
* zynqmp_disp_handle_vblank - Handle the vblank event
891-
* @disp: Display controller
892-
*
893-
* This function handles the vblank interrupt, and sends an event to
894-
* CRTC object. This will be called by the DP vblank interrupt handler.
895-
*/
896-
void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp)
897-
{
898-
struct drm_crtc *crtc = &disp->dpsub->crtc;
899-
900-
drm_crtc_handle_vblank(crtc);
901-
}
902-
903-
/**
904-
* zynqmp_disp_get_crtc_mask - Return the CRTC bit mask
905-
* @disp: Display controller
906-
*
907-
* Return: the crtc mask of the zyqnmp_disp CRTC.
908-
*/
909-
uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp)
910-
{
911-
return drm_crtc_mask(&disp->dpsub->crtc);
912-
}
913-
914869
/* -----------------------------------------------------------------------------
915870
* ZynqMP Display Layer & DRM Plane
916871
*/
@@ -1110,7 +1065,7 @@ zynqmp_disp_plane_atomic_check(struct drm_plane *plane,
11101065
false, false);
11111066
}
11121067

1113-
static void
1068+
void
11141069
zynqmp_disp_plane_atomic_disable(struct drm_plane *plane,
11151070
struct drm_atomic_state *state)
11161071
{
@@ -1300,12 +1255,12 @@ static int zynqmp_disp_layer_request_dma(struct zynqmp_disp *disp,
13001255
static int zynqmp_disp_create_layers(struct zynqmp_disp *disp)
13011256
{
13021257
static const struct zynqmp_disp_layer_info layer_info[] = {
1303-
[ZYNQMP_DISP_LAYER_VID] = {
1258+
[ZYNQMP_DPSUB_LAYER_VID] = {
13041259
.formats = avbuf_vid_fmts,
13051260
.num_formats = ARRAY_SIZE(avbuf_vid_fmts),
13061261
.num_channels = 3,
13071262
},
1308-
[ZYNQMP_DISP_LAYER_GFX] = {
1263+
[ZYNQMP_DPSUB_LAYER_GFX] = {
13091264
.formats = avbuf_gfx_fmts,
13101265
.num_formats = ARRAY_SIZE(avbuf_gfx_fmts),
13111266
.num_channels = 1,
@@ -1335,14 +1290,14 @@ static int zynqmp_disp_create_layers(struct zynqmp_disp *disp)
13351290
}
13361291

13371292
/* -----------------------------------------------------------------------------
1338-
* ZynqMP Display & DRM CRTC
1293+
* ZynqMP Display
13391294
*/
13401295

13411296
/**
13421297
* zynqmp_disp_enable - Enable the display controller
13431298
* @disp: Display controller
13441299
*/
1345-
static void zynqmp_disp_enable(struct zynqmp_disp *disp)
1300+
void zynqmp_disp_enable(struct zynqmp_disp *disp)
13461301
{
13471302
zynqmp_disp_blend_set_output_format(disp, ZYNQMP_DPSUB_FORMAT_RGB);
13481303
zynqmp_disp_blend_set_bg_color(disp, 0, 0, 0);
@@ -1362,7 +1317,7 @@ static void zynqmp_disp_enable(struct zynqmp_disp *disp)
13621317
* zynqmp_disp_disable - Disable the display controller
13631318
* @disp: Display controller
13641319
*/
1365-
static void zynqmp_disp_disable(struct zynqmp_disp *disp)
1320+
void zynqmp_disp_disable(struct zynqmp_disp *disp)
13661321
{
13671322
zynqmp_disp_audio_disable(disp);
13681323

@@ -1371,8 +1326,15 @@ static void zynqmp_disp_disable(struct zynqmp_disp *disp)
13711326
zynqmp_disp_avbuf_disable(disp);
13721327
}
13731328

1374-
static int zynqmp_disp_setup_clock(struct zynqmp_disp *disp,
1375-
unsigned long mode_clock)
1329+
/**
1330+
* zynqmp_disp_setup_clock - Configure the display controller pixel clock rate
1331+
* @disp: Display controller
1332+
* @mode_clock: The pixel clock rate, in Hz
1333+
*
1334+
* Return: 0 on success, or a negative error clock otherwise
1335+
*/
1336+
int zynqmp_disp_setup_clock(struct zynqmp_disp *disp,
1337+
unsigned long mode_clock)
13761338
{
13771339
unsigned long rate;
13781340
long diff;
@@ -1398,186 +1360,13 @@ static int zynqmp_disp_setup_clock(struct zynqmp_disp *disp,
13981360
return 0;
13991361
}
14001362

1401-
static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc)
1402-
{
1403-
return container_of(crtc, struct zynqmp_dpsub, crtc)->disp;
1404-
}
1405-
1406-
static void
1407-
zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
1408-
struct drm_atomic_state *state)
1409-
{
1410-
struct zynqmp_disp *disp = crtc_to_disp(crtc);
1411-
struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
1412-
int ret, vrefresh;
1413-
1414-
pm_runtime_get_sync(disp->dev);
1415-
1416-
zynqmp_disp_setup_clock(disp, adjusted_mode->clock * 1000);
1417-
1418-
ret = clk_prepare_enable(disp->dpsub->vid_clk);
1419-
if (ret) {
1420-
dev_err(disp->dev, "failed to enable the video clock\n");
1421-
pm_runtime_put_sync(disp->dev);
1422-
return;
1423-
}
1424-
1425-
zynqmp_disp_enable(disp);
1426-
1427-
/* Delay of 3 vblank intervals for timing gen to be stable */
1428-
vrefresh = (adjusted_mode->clock * 1000) /
1429-
(adjusted_mode->vtotal * adjusted_mode->htotal);
1430-
msleep(3 * 1000 / vrefresh);
1431-
}
1432-
1433-
static void
1434-
zynqmp_disp_crtc_atomic_disable(struct drm_crtc *crtc,
1435-
struct drm_atomic_state *state)
1436-
{
1437-
struct zynqmp_disp *disp = crtc_to_disp(crtc);
1438-
struct drm_plane_state *old_plane_state;
1439-
1440-
/*
1441-
* Disable the plane if active. The old plane state can be NULL in the
1442-
* .shutdown() path if the plane is already disabled, skip
1443-
* zynqmp_disp_plane_atomic_disable() in that case.
1444-
*/
1445-
old_plane_state = drm_atomic_get_old_plane_state(state, crtc->primary);
1446-
if (old_plane_state)
1447-
zynqmp_disp_plane_atomic_disable(crtc->primary, state);
1448-
1449-
zynqmp_disp_disable(disp);
1450-
1451-
drm_crtc_vblank_off(crtc);
1452-
1453-
spin_lock_irq(&crtc->dev->event_lock);
1454-
if (crtc->state->event) {
1455-
drm_crtc_send_vblank_event(crtc, crtc->state->event);
1456-
crtc->state->event = NULL;
1457-
}
1458-
spin_unlock_irq(&crtc->dev->event_lock);
1459-
1460-
clk_disable_unprepare(disp->dpsub->vid_clk);
1461-
pm_runtime_put_sync(disp->dev);
1462-
}
1463-
1464-
static int zynqmp_disp_crtc_atomic_check(struct drm_crtc *crtc,
1465-
struct drm_atomic_state *state)
1466-
{
1467-
return drm_atomic_add_affected_planes(state, crtc);
1468-
}
1469-
1470-
static void
1471-
zynqmp_disp_crtc_atomic_begin(struct drm_crtc *crtc,
1472-
struct drm_atomic_state *state)
1473-
{
1474-
drm_crtc_vblank_on(crtc);
1475-
}
1476-
1477-
static void
1478-
zynqmp_disp_crtc_atomic_flush(struct drm_crtc *crtc,
1479-
struct drm_atomic_state *state)
1480-
{
1481-
if (crtc->state->event) {
1482-
struct drm_pending_vblank_event *event;
1483-
1484-
/* Consume the flip_done event from atomic helper. */
1485-
event = crtc->state->event;
1486-
crtc->state->event = NULL;
1487-
1488-
event->pipe = drm_crtc_index(crtc);
1489-
1490-
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
1491-
1492-
spin_lock_irq(&crtc->dev->event_lock);
1493-
drm_crtc_arm_vblank_event(crtc, event);
1494-
spin_unlock_irq(&crtc->dev->event_lock);
1495-
}
1496-
}
1497-
1498-
static const struct drm_crtc_helper_funcs zynqmp_disp_crtc_helper_funcs = {
1499-
.atomic_enable = zynqmp_disp_crtc_atomic_enable,
1500-
.atomic_disable = zynqmp_disp_crtc_atomic_disable,
1501-
.atomic_check = zynqmp_disp_crtc_atomic_check,
1502-
.atomic_begin = zynqmp_disp_crtc_atomic_begin,
1503-
.atomic_flush = zynqmp_disp_crtc_atomic_flush,
1504-
};
1505-
1506-
static int zynqmp_disp_crtc_enable_vblank(struct drm_crtc *crtc)
1507-
{
1508-
struct zynqmp_disp *disp = crtc_to_disp(crtc);
1509-
1510-
zynqmp_dp_enable_vblank(disp->dpsub->dp);
1511-
1512-
return 0;
1513-
}
1514-
1515-
static void zynqmp_disp_crtc_disable_vblank(struct drm_crtc *crtc)
1516-
{
1517-
struct zynqmp_disp *disp = crtc_to_disp(crtc);
1518-
1519-
zynqmp_dp_disable_vblank(disp->dpsub->dp);
1520-
}
1521-
1522-
static const struct drm_crtc_funcs zynqmp_disp_crtc_funcs = {
1523-
.destroy = drm_crtc_cleanup,
1524-
.set_config = drm_atomic_helper_set_config,
1525-
.page_flip = drm_atomic_helper_page_flip,
1526-
.reset = drm_atomic_helper_crtc_reset,
1527-
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
1528-
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
1529-
.enable_vblank = zynqmp_disp_crtc_enable_vblank,
1530-
.disable_vblank = zynqmp_disp_crtc_disable_vblank,
1531-
};
1532-
1533-
static int zynqmp_disp_create_crtc(struct zynqmp_disp *disp)
1534-
{
1535-
struct drm_plane *plane = &disp->dpsub->planes[ZYNQMP_DISP_LAYER_GFX];
1536-
struct drm_crtc *crtc = &disp->dpsub->crtc;
1537-
int ret;
1538-
1539-
ret = drm_crtc_init_with_planes(disp->drm, crtc, plane,
1540-
NULL, &zynqmp_disp_crtc_funcs, NULL);
1541-
if (ret < 0)
1542-
return ret;
1543-
1544-
drm_crtc_helper_add(crtc, &zynqmp_disp_crtc_helper_funcs);
1545-
1546-
/* Start with vertical blanking interrupt reporting disabled. */
1547-
drm_crtc_vblank_off(crtc);
1548-
1549-
return 0;
1550-
}
1551-
1552-
static void zynqmp_disp_map_crtc_to_plane(struct zynqmp_disp *disp)
1553-
{
1554-
u32 possible_crtcs = drm_crtc_mask(&disp->dpsub->crtc);
1555-
unsigned int i;
1556-
1557-
for (i = 0; i < ARRAY_SIZE(disp->layers); i++)
1558-
disp->dpsub->planes[i].possible_crtcs = possible_crtcs;
1559-
}
1560-
15611363
/* -----------------------------------------------------------------------------
15621364
* Initialization & Cleanup
15631365
*/
15641366

15651367
int zynqmp_disp_drm_init(struct zynqmp_dpsub *dpsub)
15661368
{
1567-
struct zynqmp_disp *disp = dpsub->disp;
1568-
int ret;
1569-
1570-
ret = zynqmp_disp_create_planes(disp);
1571-
if (ret)
1572-
return ret;
1573-
1574-
ret = zynqmp_disp_create_crtc(disp);
1575-
if (ret < 0)
1576-
return ret;
1577-
1578-
zynqmp_disp_map_crtc_to_plane(disp);
1579-
1580-
return 0;
1369+
return zynqmp_disp_create_planes(dpsub->disp);
15811370
}
15821371

15831372
int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
@@ -1617,7 +1406,7 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
16171406
if (ret)
16181407
return ret;
16191408

1620-
layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
1409+
layer = &disp->layers[ZYNQMP_DPSUB_LAYER_VID];
16211410
dpsub->dma_align = 1 << layer->dmas[0].chan->device->copy_align;
16221411

16231412
return 0;

0 commit comments

Comments
 (0)