1
0
Fork 0

drm-misc-next for 4.19:

Core Changes:
 - add support for DisplayPort CEC-Tunneling-over-AUX (Hans Verkuil)
 - more doc updates (Daniel Vetter)
 - fourcc: Add is_yuv field to drm_format_info (Ayan Kumar Halder)
 - dma-buf: correctly place BUG_ON (Michel Dänzer)
 
 Driver Changes:
 - more vkms support(Rodrigo Siqueira)
 - many fixes and small improments to all drivers
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJbT52JAAoJEEN0HIUfOBk06UsQAIy5YwUQ9l+8GdS5bKU299KW
 ZMMi0pTgB/bg0uuqGqN1zf23kpyRTNBGu2UMZgHWTcM4gjTP9qxb5GPFyOhr5he4
 pkp0p13fcn85Mkpt6ZQQD4ErMnhJSodzPRRT+ypnM+HzcWWehQOnSbLWCTOpaCeg
 5SsSFT7RfpDcICXzZZKAHFwHAp1y1y6V027RWu0/amUTwoZPn+ktU/s0thGIdqFk
 EGb/dP4K0PAHE4ZnhZOHPFlYbVQWp0J8X7+NmkXvPgwVPahLvKbNMBfG9M3mGcku
 cMwW8phngd0ih9gd1rblG3J8pdISArg6EgqAwwUV6p8tHUBQff5mL/RTh5zrUs6D
 seLqzRM4V74WDp2meMSYogISo2b+39RiL1IhayTytdW/oaterXloSChAwKUz4pi/
 Nj3/Kn59m9DH9NoAh3DYvDg+e06U9csR6TUJZ0B6BlXIwju9/QLybsDbUdmjtSW+
 yqttEs8m4k2gB2ZRo9y2RVi/XCNv0t+GYa2HQcTGrYVZpIxKioT6WdnlobQZ6L2E
 9CClacN6v2e27cQUbZEFuU7phUkM/nw18dROFrIwJ0OxsA5nElO1DTiOy+KDwzAU
 E+l4DqZZknyxEfTxUq79+9J2HmhqA7ikQbgNJMQyQ25iRFrkvYsI7XfF4ix5z+a5
 I0/CkPP3UsTibnVhM7wn
 =HyBh
 -----END PGP SIGNATURE-----

Merge tag 'drm-misc-next-2018-07-18' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for 4.19:

Core Changes:
- add support for DisplayPort CEC-Tunneling-over-AUX (Hans Verkuil)
- more doc updates (Daniel Vetter)
- fourcc: Add is_yuv field to drm_format_info (Ayan Kumar Halder)
- dma-buf: correctly place BUG_ON (Michel Dänzer)

Driver Changes:
- more vkms support(Rodrigo Siqueira)
- many fixes and small improments to all drivers

Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180718200826.GA20165@juma
hifive-unleashed-5.1
Dave Airlie 2018-07-20 10:40:25 +10:00
commit 294f96ae8a
167 changed files with 2448 additions and 1381 deletions

View File

@ -109,6 +109,15 @@ Framebuffer CMA Helper Functions Reference
.. _drm_bridges:
Framebuffer GEM Helper Reference
================================
.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
:doc: overview
.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
:export:
Bridges
=======
@ -169,6 +178,15 @@ Display Port Helper Functions Reference
.. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c
:export:
Display Port CEC Helper Functions Reference
===========================================
.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c
:doc: dp cec helpers
.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c
:export:
Display Port Dual Mode Adaptor Helper Functions Reference
=========================================================
@ -282,13 +300,13 @@ Auxiliary Modeset Helpers
.. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
:export:
Framebuffer GEM Helper Reference
================================
OF/DT Helpers
=============
.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
.. kernel-doc:: drivers/gpu/drm/drm_of.c
:doc: overview
.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
.. kernel-doc:: drivers/gpu/drm/drm_of.c
:export:
Legacy Plane Helper Reference

View File

@ -56,11 +56,12 @@ Overview
The basic object structure KMS presents to userspace is fairly simple.
Framebuffers (represented by :c:type:`struct drm_framebuffer <drm_framebuffer>`,
see `Frame Buffer Abstraction`_) feed into planes. One or more (or even no)
planes feed their pixel data into a CRTC (represented by :c:type:`struct
drm_crtc <drm_crtc>`, see `CRTC Abstraction`_) for blending. The precise
blending step is explained in more detail in `Plane Composition Properties`_ and
related chapters.
see `Frame Buffer Abstraction`_) feed into planes. Planes are represented by
:c:type:`struct drm_plane <drm_plane>`, see `Plane Abstraction`_ for more
details. One or more (or even no) planes feed their pixel data into a CRTC
(represented by :c:type:`struct drm_crtc <drm_crtc>`, see `CRTC Abstraction`_)
for blending. The precise blending step is explained in more detail in `Plane
Composition Properties`_ and related chapters.
For the output routing the first step is encoders (represented by
:c:type:`struct drm_encoder <drm_encoder>`, see `Encoder Abstraction`_). Those
@ -466,7 +467,7 @@ Output discovery and initialization example
drm_encoder_init(dev, &intel_output->enc, &intel_crt_enc_funcs,
DRM_MODE_ENCODER_DAC);
drm_mode_connector_attach_encoder(&intel_output->base,
drm_connector_attach_encoder(&intel_output->base,
&intel_output->enc);
/* Set up the DDC bus. */

View File

@ -141,6 +141,7 @@ reservation_object_add_shared_inplace(struct reservation_object *obj,
if (signaled) {
RCU_INIT_POINTER(fobj->shared[signaled_idx], fence);
} else {
BUG_ON(fobj->shared_count >= fobj->shared_max);
RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
fobj->shared_count++;
}
@ -230,10 +231,9 @@ void reservation_object_add_shared_fence(struct reservation_object *obj,
old = reservation_object_get_list(obj);
obj->staged = NULL;
if (!fobj) {
BUG_ON(old->shared_count >= old->shared_max);
if (!fobj)
reservation_object_add_shared_inplace(obj, old, fence);
} else
else
reservation_object_add_shared_replace(obj, old, fobj, fence);
}
EXPORT_SYMBOL(reservation_object_add_shared_fence);

View File

@ -122,6 +122,16 @@ config DRM_LOAD_EDID_FIRMWARE
default case is N. Details and instructions how to build your own
EDID data are given in Documentation/EDID/HOWTO.txt.
config DRM_DP_CEC
bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support"
select CEC_CORE
help
Choose this option if you want to enable HDMI CEC support for
DisplayPort/USB-C to HDMI adapters.
Note: not all adapters support this feature, and even for those
that do support this they often do not hook up the CEC pin.
config DRM_TTM
tristate
depends on DRM && MMU

View File

@ -41,6 +41,7 @@ drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/

View File

@ -334,11 +334,11 @@ static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
int ret;
if (amdgpu_connector->edid) {
drm_mode_connector_update_edid_property(connector, amdgpu_connector->edid);
drm_connector_update_edid_property(connector, amdgpu_connector->edid);
ret = drm_add_edid_modes(connector, amdgpu_connector->edid);
return ret;
}
drm_mode_connector_update_edid_property(connector, NULL);
drm_connector_update_edid_property(connector, NULL);
return 0;
}

View File

@ -46,7 +46,7 @@ amdgpu_link_encoder_connector(struct drm_device *dev)
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
amdgpu_encoder = to_amdgpu_encoder(encoder);
if (amdgpu_encoder->devices & amdgpu_connector->devices) {
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
amdgpu_atombios_encoder_init_backlight(amdgpu_encoder, connector);
adev->mode_info.bl_encoder = amdgpu_encoder;

View File

@ -627,7 +627,7 @@ static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
drm_connector_register(connector);
/* link them */
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -903,14 +903,14 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector)
(struct edid *) sink->dc_edid.raw_edid;
drm_mode_connector_update_edid_property(connector,
drm_connector_update_edid_property(connector,
aconnector->edid);
}
amdgpu_dm_add_sink_to_freesync_module(connector, aconnector->edid);
} else {
amdgpu_dm_remove_sink_from_freesync_module(connector);
drm_mode_connector_update_edid_property(connector, NULL);
drm_connector_update_edid_property(connector, NULL);
aconnector->num_modes = 0;
aconnector->dc_sink = NULL;
aconnector->edid = NULL;
@ -3663,7 +3663,7 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
link,
link_index);
drm_mode_connector_attach_encoder(
drm_connector_attach_encoder(
&aconnector->base, &aencoder->base);
drm_connector_register(&aconnector->base);

View File

@ -233,7 +233,7 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);
if (!edid) {
drm_mode_connector_update_edid_property(
drm_connector_update_edid_property(
&aconnector->base,
NULL);
return ret;
@ -261,7 +261,7 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
connector, aconnector->edid);
}
drm_mode_connector_update_edid_property(
drm_connector_update_edid_property(
&aconnector->base, aconnector->edid);
ret = drm_add_edid_modes(connector, aconnector->edid);
@ -345,7 +345,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
aconnector, connector->base.id, aconnector->mst_port);
aconnector->port = port;
drm_mode_connector_set_path_property(connector, pathprop);
drm_connector_set_path_property(connector, pathprop);
drm_connector_list_iter_end(&conn_iter);
aconnector->mst_connected = true;
@ -393,7 +393,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
dev->mode_config.tile_property,
0);
drm_mode_connector_set_path_property(connector, pathprop);
drm_connector_set_path_property(connector, pathprop);
/*
* Initialize connector state before adding the connectror to drm and
@ -441,7 +441,7 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
static void dm_dp_mst_link_status_reset(struct drm_connector *connector)
{
mutex_lock(&connector->dev->mode_config.mutex);
drm_mode_connector_set_link_status_property(connector, DRM_MODE_LINK_STATUS_BAD);
drm_connector_set_link_status_property(connector, DRM_MODE_LINK_STATUS_BAD);
mutex_unlock(&connector->dev->mode_config.mutex);
}

View File

@ -99,7 +99,7 @@ int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np)
goto error_encoder_cleanup;
}
ret = drm_mode_connector_attach_encoder(connector, encoder);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret < 0) {
dev_err(drm->dev, "could not attach connector to encoder\n");
drm_connector_unregister(connector);

View File

@ -790,12 +790,12 @@ static int ast_get_modes(struct drm_connector *connector)
if (!flags)
edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
if (edid) {
drm_mode_connector_update_edid_property(&ast_connector->base, edid);
drm_connector_update_edid_property(&ast_connector->base, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
return ret;
} else
drm_mode_connector_update_edid_property(&ast_connector->base, NULL);
drm_connector_update_edid_property(&ast_connector->base, NULL);
return 0;
}
@ -900,7 +900,7 @@ static int ast_connector_init(struct drm_device *dev)
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
encoder = list_first_entry(&dev->mode_config.encoder_list, struct drm_encoder, head);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
ast_connector->i2c = ast_i2c_create(dev);
if (!ast_connector->i2c)

View File

@ -259,7 +259,7 @@ int bochs_kms_init(struct bochs_device *bochs)
bochs_crtc_init(bochs->dev);
bochs_encoder_init(bochs->dev);
bochs_connector_init(bochs->dev);
drm_mode_connector_attach_encoder(&bochs->connector,
drm_connector_attach_encoder(&bochs->connector,
&bochs->encoder);
return 0;

View File

@ -601,7 +601,7 @@ static int adv7511_get_modes(struct adv7511 *adv7511,
__adv7511_power_off(adv7511);
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
count = drm_add_edid_modes(connector, edid);
adv7511_set_config_csc(adv7511, connector, adv7511->rgb,
@ -860,7 +860,7 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge)
}
drm_connector_helper_add(&adv->connector,
&adv7511_connector_helper_funcs);
drm_mode_connector_attach_encoder(&adv->connector, bridge->encoder);
drm_connector_attach_encoder(&adv->connector, bridge->encoder);
if (adv->type == ADV7533)
ret = adv7533_attach_dsi(adv);

View File

@ -969,8 +969,8 @@ static int anx78xx_get_modes(struct drm_connector *connector)
goto unlock;
}
err = drm_mode_connector_update_edid_property(connector,
anx78xx->edid);
err = drm_connector_update_edid_property(connector,
anx78xx->edid);
if (err) {
DRM_ERROR("Failed to update EDID property: %d\n", err);
goto unlock;
@ -1048,8 +1048,8 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge)
anx78xx->connector.polled = DRM_CONNECTOR_POLL_HPD;
err = drm_mode_connector_attach_encoder(&anx78xx->connector,
bridge->encoder);
err = drm_connector_attach_encoder(&anx78xx->connector,
bridge->encoder);
if (err) {
DRM_ERROR("Failed to link up connector to encoder: %d\n", err);
return err;

View File

@ -1119,8 +1119,8 @@ static int analogix_dp_get_modes(struct drm_connector *connector)
edid = drm_get_edid(connector, &dp->aux.ddc);
pm_runtime_put(dp->dev);
if (edid) {
drm_mode_connector_update_edid_property(&dp->connector,
edid);
drm_connector_update_edid_property(&dp->connector,
edid);
num_modes += drm_add_edid_modes(&dp->connector, edid);
kfree(edid);
}
@ -1210,7 +1210,7 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge)
drm_connector_helper_add(connector,
&analogix_dp_connector_helper_funcs);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
}
/*

View File

@ -55,7 +55,7 @@ static int dumb_vga_get_modes(struct drm_connector *connector)
goto fallback;
}
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
return ret;
@ -122,7 +122,7 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
return ret;
}
drm_mode_connector_attach_encoder(&vga->connector,
drm_connector_attach_encoder(&vga->connector,
bridge->encoder);
return 0;

View File

@ -152,7 +152,7 @@ static int ge_b850v3_lvds_get_modes(struct drm_connector *connector)
ge_b850v3_lvds_ptr->edid = (struct edid *)stdp2690_get_edid(client);
if (ge_b850v3_lvds_ptr->edid) {
drm_mode_connector_update_edid_property(connector,
drm_connector_update_edid_property(connector,
ge_b850v3_lvds_ptr->edid);
num_modes = drm_add_edid_modes(connector,
ge_b850v3_lvds_ptr->edid);
@ -241,7 +241,7 @@ static int ge_b850v3_lvds_attach(struct drm_bridge *bridge)
return ret;
}
ret = drm_mode_connector_attach_encoder(connector, bridge->encoder);
ret = drm_connector_attach_encoder(connector, bridge->encoder);
if (ret)
return ret;

View File

@ -222,7 +222,7 @@ static int ptn3460_get_modes(struct drm_connector *connector)
}
ptn_bridge->edid = (struct edid *)edid;
drm_mode_connector_update_edid_property(connector, ptn_bridge->edid);
drm_connector_update_edid_property(connector, ptn_bridge->edid);
num_modes = drm_add_edid_modes(connector, ptn_bridge->edid);
@ -265,7 +265,7 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge)
drm_connector_helper_add(&ptn_bridge->connector,
&ptn3460_connector_helper_funcs);
drm_connector_register(&ptn_bridge->connector);
drm_mode_connector_attach_encoder(&ptn_bridge->connector,
drm_connector_attach_encoder(&ptn_bridge->connector,
bridge->encoder);
if (ptn_bridge->panel)

View File

@ -79,7 +79,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge)
return ret;
}
drm_mode_connector_attach_encoder(&panel_bridge->connector,
drm_connector_attach_encoder(&panel_bridge->connector,
bridge->encoder);
ret = drm_panel_attach(panel_bridge->panel, &panel_bridge->connector);

View File

@ -503,7 +503,7 @@ static int ps8622_attach(struct drm_bridge *bridge)
drm_connector_helper_add(&ps8622->connector,
&ps8622_connector_helper_funcs);
drm_connector_register(&ps8622->connector);
drm_mode_connector_attach_encoder(&ps8622->connector,
drm_connector_attach_encoder(&ps8622->connector,
bridge->encoder);
if (ps8622->panel)

View File

@ -170,7 +170,7 @@ static int sii902x_get_modes(struct drm_connector *connector)
return ret;
edid = drm_get_edid(connector, sii902x->i2c->adapter);
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
if (edid) {
num = drm_add_edid_modes(connector, edid);
kfree(edid);
@ -324,7 +324,7 @@ static int sii902x_bridge_attach(struct drm_bridge *bridge)
else
sii902x->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
drm_mode_connector_attach_encoder(&sii902x->connector, bridge->encoder);
drm_connector_attach_encoder(&sii902x->connector, bridge->encoder);
return 0;
}

View File

@ -1922,7 +1922,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
@ -1974,7 +1974,7 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -1140,7 +1140,7 @@ static int tc_connector_get_modes(struct drm_connector *connector)
if (!edid)
return 0;
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
count = drm_add_edid_modes(connector, edid);
return count;
@ -1195,7 +1195,7 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
drm_display_info_set_bus_formats(&tc->connector.display_info,
&bus_format, 1);
drm_mode_connector_attach_encoder(&tc->connector, tc->bridge.encoder);
drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder);
return 0;
}

View File

@ -62,7 +62,7 @@ static int tfp410_get_modes(struct drm_connector *connector)
goto fallback;
}
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
return drm_add_edid_modes(connector, edid);
fallback:
@ -132,7 +132,7 @@ static int tfp410_attach(struct drm_bridge *bridge)
return ret;
}
drm_mode_connector_attach_encoder(&dvi->connector,
drm_connector_attach_encoder(&dvi->connector,
bridge->encoder);
return 0;

View File

@ -530,7 +530,7 @@ int cirrus_modeset_init(struct cirrus_device *cdev)
return -1;
}
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
ret = cirrus_fbdev_init(cdev);
if (ret) {

View File

@ -2867,7 +2867,7 @@ static int update_output_state(struct drm_atomic_state *state,
* resets the "link-status" property to GOOD, to force any link
* re-training. The SETCRTC ioctl does not define whether an update does
* need a full modeset or just a plane update, hence we're allowed to do
* that. See also drm_mode_connector_set_link_status_property().
* that. See also drm_connector_set_link_status_property().
*
* Returns:
* Returns 0 on success, negative errno numbers on failure.

View File

@ -218,7 +218,9 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
if (buffer->gem)
drm_gem_object_put_unlocked(buffer->gem);
drm_mode_destroy_dumb(dev, buffer->handle, buffer->client->file);
if (buffer->handle)
drm_mode_destroy_dumb(dev, buffer->handle, buffer->client->file);
kfree(buffer);
}
@ -243,7 +245,7 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
dumb_args.bpp = drm_format_plane_cpp(format, 0) * 8;
ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
if (ret)
goto err_free;
goto err_delete;
buffer->handle = dumb_args.handle;
buffer->pitch = dumb_args.pitch;
@ -276,8 +278,6 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
err_delete:
drm_client_buffer_delete(buffer);
err_free:
kfree(buffer);
return ERR_PTR(ret);
}

View File

@ -48,7 +48,7 @@
*
* Connectors must be attached to an encoder to be used. For devices that map
* connectors to encoders 1:1, the connector should be attached at
* initialization time with a call to drm_mode_connector_attach_encoder(). The
* initialization time with a call to drm_connector_attach_encoder(). The
* driver must also set the &drm_connector.encoder field to point to the
* attached encoder.
*
@ -291,7 +291,7 @@ out_put:
EXPORT_SYMBOL(drm_connector_init);
/**
* drm_mode_connector_attach_encoder - attach a connector to an encoder
* drm_connector_attach_encoder - attach a connector to an encoder
* @connector: connector to attach
* @encoder: encoder to attach @connector to
*
@ -302,8 +302,8 @@ EXPORT_SYMBOL(drm_connector_init);
* Returns:
* Zero on success, negative errno on failure.
*/
int drm_mode_connector_attach_encoder(struct drm_connector *connector,
struct drm_encoder *encoder)
int drm_connector_attach_encoder(struct drm_connector *connector,
struct drm_encoder *encoder)
{
int i;
@ -329,7 +329,7 @@ int drm_mode_connector_attach_encoder(struct drm_connector *connector,
}
return -ENOMEM;
}
EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
EXPORT_SYMBOL(drm_connector_attach_encoder);
/**
* drm_connector_has_possible_encoder - check if the connector and encoder are assosicated with each other
@ -606,7 +606,7 @@ __drm_connector_put_safe(struct drm_connector *conn)
/**
* drm_connector_list_iter_next - return next connector
* @iter: connectr_list iterator
* @iter: connector_list iterator
*
* Returns the next connector for @iter, or NULL when the list walk has
* completed.
@ -814,7 +814,7 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
* Blob property which contains the current EDID read from the sink. This
* is useful to parse sink identification information like vendor, model
* and serial. Drivers should update this property by calling
* drm_mode_connector_update_edid_property(), usually after having parsed
* drm_connector_update_edid_property(), usually after having parsed
* the EDID using drm_add_edid_modes(). Userspace cannot change this
* property.
* DPMS:
@ -852,7 +852,7 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
* PATH:
* Connector path property to identify how this sink is physically
* connected. Used by DP MST. This should be set by calling
* drm_mode_connector_set_path_property(), in the case of DP MST with the
* drm_connector_set_path_property(), in the case of DP MST with the
* path property the MST manager created. Userspace cannot change this
* property.
* TILE:
@ -863,14 +863,14 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
* are not gen-locked. Note that for tiled panels which are genlocked, like
* dual-link LVDS or dual-link DSI, the driver should try to not expose the
* tiling and virtualize both &drm_crtc and &drm_plane if needed. Drivers
* should update this value using drm_mode_connector_set_tile_property().
* should update this value using drm_connector_set_tile_property().
* Userspace cannot change this property.
* link-status:
* Connector link-status property to indicate the status of link. The
* default value of link-status is "GOOD". If something fails during or
* after modeset, the kernel driver may set this to "BAD" and issue a
* hotplug uevent. Drivers should update this value using
* drm_mode_connector_set_link_status_property().
* drm_connector_set_link_status_property().
* non_desktop:
* Indicates the output should be ignored for purposes of displaying a
* standard desktop environment or console. This is most likely because
@ -1425,7 +1425,7 @@ int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
/**
* drm_mode_connector_set_path_property - set tile property on connector
* drm_connector_set_path_property - set tile property on connector
* @connector: connector to set property on.
* @path: path to use for property; must not be NULL.
*
@ -1437,8 +1437,8 @@ EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
* Returns:
* Zero on success, negative errno on failure.
*/
int drm_mode_connector_set_path_property(struct drm_connector *connector,
const char *path)
int drm_connector_set_path_property(struct drm_connector *connector,
const char *path)
{
struct drm_device *dev = connector->dev;
int ret;
@ -1451,10 +1451,10 @@ int drm_mode_connector_set_path_property(struct drm_connector *connector,
dev->mode_config.path_property);
return ret;
}
EXPORT_SYMBOL(drm_mode_connector_set_path_property);
EXPORT_SYMBOL(drm_connector_set_path_property);
/**
* drm_mode_connector_set_tile_property - set tile property on connector
* drm_connector_set_tile_property - set tile property on connector
* @connector: connector to set property on.
*
* This looks up the tile information for a connector, and creates a
@ -1464,7 +1464,7 @@ EXPORT_SYMBOL(drm_mode_connector_set_path_property);
* Returns:
* Zero on success, errno on failure.
*/
int drm_mode_connector_set_tile_property(struct drm_connector *connector)
int drm_connector_set_tile_property(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
char tile[256];
@ -1494,10 +1494,10 @@ int drm_mode_connector_set_tile_property(struct drm_connector *connector)
dev->mode_config.tile_property);
return ret;
}
EXPORT_SYMBOL(drm_mode_connector_set_tile_property);
EXPORT_SYMBOL(drm_connector_set_tile_property);
/**
* drm_mode_connector_update_edid_property - update the edid property of a connector
* drm_connector_update_edid_property - update the edid property of a connector
* @connector: drm connector
* @edid: new value of the edid property
*
@ -1507,8 +1507,8 @@ EXPORT_SYMBOL(drm_mode_connector_set_tile_property);
* Returns:
* Zero on success, negative errno on failure.
*/
int drm_mode_connector_update_edid_property(struct drm_connector *connector,
const struct edid *edid)
int drm_connector_update_edid_property(struct drm_connector *connector,
const struct edid *edid)
{
struct drm_device *dev = connector->dev;
size_t size = 0;
@ -1546,10 +1546,10 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
dev->mode_config.edid_property);
return ret;
}
EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
EXPORT_SYMBOL(drm_connector_update_edid_property);
/**
* drm_mode_connector_set_link_status_property - Set link status property of a connector
* drm_connector_set_link_status_property - Set link status property of a connector
* @connector: drm connector
* @link_status: new value of link status property (0: Good, 1: Bad)
*
@ -1567,8 +1567,8 @@ EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
* it is not limited to DP or link training. For example, if we implement
* asynchronous setcrtc, this property can be used to report any failures in that.
*/
void drm_mode_connector_set_link_status_property(struct drm_connector *connector,
uint64_t link_status)
void drm_connector_set_link_status_property(struct drm_connector *connector,
uint64_t link_status)
{
struct drm_device *dev = connector->dev;
@ -1576,7 +1576,7 @@ void drm_mode_connector_set_link_status_property(struct drm_connector *connector
connector->state->link_status = link_status;
drm_modeset_unlock(&dev->mode_config.connection_mutex);
}
EXPORT_SYMBOL(drm_mode_connector_set_link_status_property);
EXPORT_SYMBOL(drm_connector_set_link_status_property);
/**
* drm_connector_init_panel_orientation_property -
@ -1629,7 +1629,7 @@ int drm_connector_init_panel_orientation_property(
}
EXPORT_SYMBOL(drm_connector_init_panel_orientation_property);
int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
int drm_connector_set_obj_prop(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t value)
{
@ -1647,8 +1647,8 @@ int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
return ret;
}
int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
int drm_connector_property_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_mode_connector_set_property *conn_set_prop = data;
struct drm_mode_obj_set_property obj_set_prop = {

View File

@ -461,6 +461,8 @@ static int __drm_mode_set_config_internal(struct drm_mode_set *set,
struct drm_crtc *tmp;
int ret;
WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
/*
* NOTE: ->set_config can also disable other crtcs (if we steal all
* connectors from it), hence we need to refcount the fbs across all
@ -478,10 +480,8 @@ static int __drm_mode_set_config_internal(struct drm_mode_set *set,
if (ret == 0) {
struct drm_plane *plane = crtc->primary;
if (!plane->state) {
plane->crtc = fb ? crtc : NULL;
plane->fb = fb;
}
plane->crtc = fb ? crtc : NULL;
plane->fb = fb;
}
drm_for_each_crtc(tmp, crtc->dev) {
@ -496,6 +496,7 @@ static int __drm_mode_set_config_internal(struct drm_mode_set *set,
return ret;
}
/**
* drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config
* @set: modeset config to set
@ -740,7 +741,11 @@ retry:
set.connectors = connector_set;
set.num_connectors = crtc_req->count_connectors;
set.fb = fb;
ret = __drm_mode_set_config_internal(&set, &ctx);
if (drm_drv_uses_atomic_modeset(dev))
ret = crtc->funcs->set_config(&set, &ctx);
else
ret = __drm_mode_set_config_internal(&set, &ctx);
out:
if (fb)

View File

@ -148,7 +148,7 @@ void drm_connector_ida_init(void);
void drm_connector_ida_destroy(void);
void drm_connector_unregister_all(struct drm_device *dev);
int drm_connector_register_all(struct drm_device *dev);
int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
int drm_connector_set_obj_prop(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t value);
int drm_connector_create_standard_properties(struct drm_device *dev);
@ -156,8 +156,8 @@ const char *drm_get_connector_force_name(enum drm_connector_force force);
void drm_connector_free_work_fn(struct work_struct *work);
/* IOCTL */
int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
int drm_connector_property_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
int drm_mode_getconnector(struct drm_device *dev,
void *data, struct drm_file *file_priv);

View File

@ -314,13 +314,13 @@ static ssize_t edid_write(struct file *file, const char __user *ubuf,
if (len == 5 && !strncmp(buf, "reset", 5)) {
connector->override_edid = false;
ret = drm_mode_connector_update_edid_property(connector, NULL);
ret = drm_connector_update_edid_property(connector, NULL);
} else if (len < EDID_LENGTH ||
EDID_LENGTH * (1 + edid->extensions) > len)
ret = -EINVAL;
else {
connector->override_edid = false;
ret = drm_mode_connector_update_edid_property(connector, edid);
ret = drm_connector_update_edid_property(connector, edid);
if (!ret)
connector->override_edid = true;
}

View File

@ -0,0 +1,428 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DisplayPort CEC-Tunneling-over-AUX support
*
* Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <drm/drm_dp_helper.h>
#include <media/cec.h>
/*
* Unfortunately it turns out that we have a chicken-and-egg situation
* here. Quite a few active (mini-)DP-to-HDMI or USB-C-to-HDMI adapters
* have a converter chip that supports CEC-Tunneling-over-AUX (usually the
* Parade PS176), but they do not wire up the CEC pin, thus making CEC
* useless.
*
* Sadly there is no way for this driver to know this. What happens is
* that a /dev/cecX device is created that is isolated and unable to see
* any of the other CEC devices. Quite literally the CEC wire is cut
* (or in this case, never connected in the first place).
*
* The reason so few adapters support this is that this tunneling protocol
* was never supported by any OS. So there was no easy way of testing it,
* and no incentive to correctly wire up the CEC pin.
*
* Hopefully by creating this driver it will be easier for vendors to
* finally fix their adapters and test the CEC functionality.
*
* I keep a list of known working adapters here:
*
* https://hverkuil.home.xs4all.nl/cec-status.txt
*
* Please mail me (hverkuil@xs4all.nl) if you find an adapter that works
* and is not yet listed there.
*
* Note that the current implementation does not support CEC over an MST hub.
* As far as I can see there is no mechanism defined in the DisplayPort
* standard to transport CEC interrupts over an MST device. It might be
* possible to do this through polling, but I have not been able to get that
* to work.
*/
/**
* DOC: dp cec helpers
*
* These functions take care of supporting the CEC-Tunneling-over-AUX
* feature of DisplayPort-to-HDMI adapters.
*/
/*
* When the EDID is unset because the HPD went low, then the CEC DPCD registers
* typically can no longer be read (true for a DP-to-HDMI adapter since it is
* powered by the HPD). However, some displays toggle the HPD off and on for a
* short period for one reason or another, and that would cause the CEC adapter
* to be removed and added again, even though nothing else changed.
*
* This module parameter sets a delay in seconds before the CEC adapter is
* actually unregistered. Only if the HPD does not return within that time will
* the CEC adapter be unregistered.
*
* If it is set to a value >= NEVER_UNREG_DELAY, then the CEC adapter will never
* be unregistered for as long as the connector remains registered.
*
* If it is set to 0, then the CEC adapter will be unregistered immediately as
* soon as the HPD disappears.
*
* The default is one second to prevent short HPD glitches from unregistering
* the CEC adapter.
*
* Note that for integrated HDMI branch devices that support CEC the DPCD
* registers remain available even if the HPD goes low since it is not powered
* by the HPD. In that case the CEC adapter will never be unregistered during
* the life time of the connector. At least, this is the theory since I do not
* have hardware with an integrated HDMI branch device that supports CEC.
*/
#define NEVER_UNREG_DELAY 1000
static unsigned int drm_dp_cec_unregister_delay = 1;
module_param(drm_dp_cec_unregister_delay, uint, 0600);
MODULE_PARM_DESC(drm_dp_cec_unregister_delay,
"CEC unregister delay in seconds, 0: no delay, >= 1000: never unregister");
static int drm_dp_cec_adap_enable(struct cec_adapter *adap, bool enable)
{
struct drm_dp_aux *aux = cec_get_drvdata(adap);
u32 val = enable ? DP_CEC_TUNNELING_ENABLE : 0;
ssize_t err = 0;
err = drm_dp_dpcd_writeb(aux, DP_CEC_TUNNELING_CONTROL, val);
return (enable && err < 0) ? err : 0;
}
static int drm_dp_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
{
struct drm_dp_aux *aux = cec_get_drvdata(adap);
/* Bit 15 (logical address 15) should always be set */
u16 la_mask = 1 << CEC_LOG_ADDR_BROADCAST;
u8 mask[2];
ssize_t err;
if (addr != CEC_LOG_ADDR_INVALID)
la_mask |= adap->log_addrs.log_addr_mask | (1 << addr);
mask[0] = la_mask & 0xff;
mask[1] = la_mask >> 8;
err = drm_dp_dpcd_write(aux, DP_CEC_LOGICAL_ADDRESS_MASK, mask, 2);
return (addr != CEC_LOG_ADDR_INVALID && err < 0) ? err : 0;
}
static int drm_dp_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
u32 signal_free_time, struct cec_msg *msg)
{
struct drm_dp_aux *aux = cec_get_drvdata(adap);
unsigned int retries = min(5, attempts - 1);
ssize_t err;
err = drm_dp_dpcd_write(aux, DP_CEC_TX_MESSAGE_BUFFER,
msg->msg, msg->len);
if (err < 0)
return err;
err = drm_dp_dpcd_writeb(aux, DP_CEC_TX_MESSAGE_INFO,
(msg->len - 1) | (retries << 4) |
DP_CEC_TX_MESSAGE_SEND);
return err < 0 ? err : 0;
}
static int drm_dp_cec_adap_monitor_all_enable(struct cec_adapter *adap,
bool enable)
{
struct drm_dp_aux *aux = cec_get_drvdata(adap);
ssize_t err;
u8 val;
if (!(adap->capabilities & CEC_CAP_MONITOR_ALL))
return 0;
err = drm_dp_dpcd_readb(aux, DP_CEC_TUNNELING_CONTROL, &val);
if (err >= 0) {
if (enable)
val |= DP_CEC_SNOOPING_ENABLE;
else
val &= ~DP_CEC_SNOOPING_ENABLE;
err = drm_dp_dpcd_writeb(aux, DP_CEC_TUNNELING_CONTROL, val);
}
return (enable && err < 0) ? err : 0;
}
static void drm_dp_cec_adap_status(struct cec_adapter *adap,
struct seq_file *file)
{
struct drm_dp_aux *aux = cec_get_drvdata(adap);
struct drm_dp_desc desc;
struct drm_dp_dpcd_ident *id = &desc.ident;
if (drm_dp_read_desc(aux, &desc, true))
return;
seq_printf(file, "OUI: %*pdH\n",
(int)sizeof(id->oui), id->oui);
seq_printf(file, "ID: %*pE\n",
(int)strnlen(id->device_id, sizeof(id->device_id)),
id->device_id);
seq_printf(file, "HW Rev: %d.%d\n", id->hw_rev >> 4, id->hw_rev & 0xf);
/*
* Show this both in decimal and hex: at least one vendor
* always reports this in hex.
*/
seq_printf(file, "FW/SW Rev: %d.%d (0x%02x.0x%02x)\n",
id->sw_major_rev, id->sw_minor_rev,
id->sw_major_rev, id->sw_minor_rev);
}
static const struct cec_adap_ops drm_dp_cec_adap_ops = {
.adap_enable = drm_dp_cec_adap_enable,
.adap_log_addr = drm_dp_cec_adap_log_addr,
.adap_transmit = drm_dp_cec_adap_transmit,
.adap_monitor_all_enable = drm_dp_cec_adap_monitor_all_enable,
.adap_status = drm_dp_cec_adap_status,
};
static int drm_dp_cec_received(struct drm_dp_aux *aux)
{
struct cec_adapter *adap = aux->cec.adap;
struct cec_msg msg;
u8 rx_msg_info;
ssize_t err;
err = drm_dp_dpcd_readb(aux, DP_CEC_RX_MESSAGE_INFO, &rx_msg_info);
if (err < 0)
return err;
if (!(rx_msg_info & DP_CEC_RX_MESSAGE_ENDED))
return 0;
msg.len = (rx_msg_info & DP_CEC_RX_MESSAGE_LEN_MASK) + 1;
err = drm_dp_dpcd_read(aux, DP_CEC_RX_MESSAGE_BUFFER, msg.msg, msg.len);
if (err < 0)
return err;
cec_received_msg(adap, &msg);
return 0;
}
static void drm_dp_cec_handle_irq(struct drm_dp_aux *aux)
{
struct cec_adapter *adap = aux->cec.adap;
u8 flags;
if (drm_dp_dpcd_readb(aux, DP_CEC_TUNNELING_IRQ_FLAGS, &flags) < 0)
return;
if (flags & DP_CEC_RX_MESSAGE_INFO_VALID)
drm_dp_cec_received(aux);
if (flags & DP_CEC_TX_MESSAGE_SENT)
cec_transmit_attempt_done(adap, CEC_TX_STATUS_OK);
else if (flags & DP_CEC_TX_LINE_ERROR)
cec_transmit_attempt_done(adap, CEC_TX_STATUS_ERROR |
CEC_TX_STATUS_MAX_RETRIES);
else if (flags &
(DP_CEC_TX_ADDRESS_NACK_ERROR | DP_CEC_TX_DATA_NACK_ERROR))
cec_transmit_attempt_done(adap, CEC_TX_STATUS_NACK |
CEC_TX_STATUS_MAX_RETRIES);
drm_dp_dpcd_writeb(aux, DP_CEC_TUNNELING_IRQ_FLAGS, flags);
}
/**
* drm_dp_cec_irq() - handle CEC interrupt, if any
* @aux: DisplayPort AUX channel
*
* Should be called when handling an IRQ_HPD request. If CEC-tunneling-over-AUX
* is present, then it will check for a CEC_IRQ and handle it accordingly.
*/
void drm_dp_cec_irq(struct drm_dp_aux *aux)
{
u8 cec_irq;
int ret;
mutex_lock(&aux->cec.lock);
if (!aux->cec.adap)
goto unlock;
ret = drm_dp_dpcd_readb(aux, DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1,
&cec_irq);
if (ret < 0 || !(cec_irq & DP_CEC_IRQ))
goto unlock;
drm_dp_cec_handle_irq(aux);
drm_dp_dpcd_writeb(aux, DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1, DP_CEC_IRQ);
unlock:
mutex_unlock(&aux->cec.lock);
}
EXPORT_SYMBOL(drm_dp_cec_irq);
static bool drm_dp_cec_cap(struct drm_dp_aux *aux, u8 *cec_cap)
{
u8 cap = 0;
if (drm_dp_dpcd_readb(aux, DP_CEC_TUNNELING_CAPABILITY, &cap) != 1 ||
!(cap & DP_CEC_TUNNELING_CAPABLE))
return false;
if (cec_cap)
*cec_cap = cap;
return true;
}
/*
* Called if the HPD was low for more than drm_dp_cec_unregister_delay
* seconds. This unregisters the CEC adapter.
*/
static void drm_dp_cec_unregister_work(struct work_struct *work)
{
struct drm_dp_aux *aux = container_of(work, struct drm_dp_aux,
cec.unregister_work.work);
mutex_lock(&aux->cec.lock);
cec_unregister_adapter(aux->cec.adap);
aux->cec.adap = NULL;
mutex_unlock(&aux->cec.lock);
}
/*
* A new EDID is set. If there is no CEC adapter, then create one. If
* there was a CEC adapter, then check if the CEC adapter properties
* were unchanged and just update the CEC physical address. Otherwise
* unregister the old CEC adapter and create a new one.
*/
void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid)
{
u32 cec_caps = CEC_CAP_DEFAULTS | CEC_CAP_NEEDS_HPD;
unsigned int num_las = 1;
u8 cap;
#ifndef CONFIG_MEDIA_CEC_RC
/*
* CEC_CAP_RC is part of CEC_CAP_DEFAULTS, but it is stripped by
* cec_allocate_adapter() if CONFIG_MEDIA_CEC_RC is undefined.
*
* Do this here as well to ensure the tests against cec_caps are
* correct.
*/
cec_caps &= ~CEC_CAP_RC;
#endif
cancel_delayed_work_sync(&aux->cec.unregister_work);
mutex_lock(&aux->cec.lock);
if (!drm_dp_cec_cap(aux, &cap)) {
/* CEC is not supported, unregister any existing adapter */
cec_unregister_adapter(aux->cec.adap);
aux->cec.adap = NULL;
goto unlock;
}
if (cap & DP_CEC_SNOOPING_CAPABLE)
cec_caps |= CEC_CAP_MONITOR_ALL;
if (cap & DP_CEC_MULTIPLE_LA_CAPABLE)
num_las = CEC_MAX_LOG_ADDRS;
if (aux->cec.adap) {
if (aux->cec.adap->capabilities == cec_caps &&
aux->cec.adap->available_log_addrs == num_las) {
/* Unchanged, so just set the phys addr */
cec_s_phys_addr_from_edid(aux->cec.adap, edid);
goto unlock;
}
/*
* The capabilities changed, so unregister the old
* adapter first.
*/
cec_unregister_adapter(aux->cec.adap);
}
/* Create a new adapter */
aux->cec.adap = cec_allocate_adapter(&drm_dp_cec_adap_ops,
aux, aux->cec.name, cec_caps,
num_las);
if (IS_ERR(aux->cec.adap)) {
aux->cec.adap = NULL;
goto unlock;
}
if (cec_register_adapter(aux->cec.adap, aux->cec.parent)) {
cec_delete_adapter(aux->cec.adap);
aux->cec.adap = NULL;
} else {
/*
* Update the phys addr for the new CEC adapter. When called
* from drm_dp_cec_register_connector() edid == NULL, so in
* that case the phys addr is just invalidated.
*/
cec_s_phys_addr_from_edid(aux->cec.adap, edid);
}
unlock:
mutex_unlock(&aux->cec.lock);
}
EXPORT_SYMBOL(drm_dp_cec_set_edid);
/*
* The EDID disappeared (likely because of the HPD going down).
*/
void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
{
cancel_delayed_work_sync(&aux->cec.unregister_work);
mutex_lock(&aux->cec.lock);
if (!aux->cec.adap)
goto unlock;
cec_phys_addr_invalidate(aux->cec.adap);
/*
* We're done if we want to keep the CEC device
* (drm_dp_cec_unregister_delay is >= NEVER_UNREG_DELAY) or if the
* DPCD still indicates the CEC capability (expected for an integrated
* HDMI branch device).
*/
if (drm_dp_cec_unregister_delay < NEVER_UNREG_DELAY &&
!drm_dp_cec_cap(aux, NULL)) {
/*
* Unregister the CEC adapter after drm_dp_cec_unregister_delay
* seconds. This to debounce short HPD off-and-on cycles from
* displays.
*/
schedule_delayed_work(&aux->cec.unregister_work,
drm_dp_cec_unregister_delay * HZ);
}
unlock:
mutex_unlock(&aux->cec.lock);
}
EXPORT_SYMBOL(drm_dp_cec_unset_edid);
/**
* drm_dp_cec_register_connector() - register a new connector
* @aux: DisplayPort AUX channel
* @name: name of the CEC device
* @parent: parent device
*
* A new connector was registered with associated CEC adapter name and
* CEC adapter parent device. After registering the name and parent
* drm_dp_cec_set_edid() is called to check if the connector supports
* CEC and to register a CEC adapter if that is the case.
*/
void drm_dp_cec_register_connector(struct drm_dp_aux *aux, const char *name,
struct device *parent)
{
WARN_ON(aux->cec.adap);
aux->cec.name = name;
aux->cec.parent = parent;
INIT_DELAYED_WORK(&aux->cec.unregister_work,
drm_dp_cec_unregister_work);
drm_dp_cec_set_edid(aux, NULL);
}
EXPORT_SYMBOL(drm_dp_cec_register_connector);
/**
* drm_dp_cec_unregister_connector() - unregister the CEC adapter, if any
* @aux: DisplayPort AUX channel
*/
void drm_dp_cec_unregister_connector(struct drm_dp_aux *aux)
{
if (!aux->cec.adap)
return;
cancel_delayed_work_sync(&aux->cec.unregister_work);
cec_unregister_adapter(aux->cec.adap);
aux->cec.adap = NULL;
}
EXPORT_SYMBOL(drm_dp_cec_unregister_connector);

View File

@ -185,6 +185,20 @@ EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
#define AUX_RETRY_INTERVAL 500 /* us */
static inline void
drm_dp_dump_access(const struct drm_dp_aux *aux,
u8 request, uint offset, void *buffer, int ret)
{
const char *arrow = request == DP_AUX_NATIVE_READ ? "->" : "<-";
if (ret > 0)
drm_dbg(DRM_UT_DP, "%s: 0x%05x AUX %s (ret=%3d) %*ph\n",
aux->name, offset, arrow, ret, min(ret, 20), buffer);
else
drm_dbg(DRM_UT_DP, "%s: 0x%05x AUX %s (ret=%3d)\n",
aux->name, offset, arrow, ret);
}
/**
* DOC: dp helpers
*
@ -288,10 +302,14 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, DP_DPCD_REV, buffer,
1);
if (ret != 1)
return ret;
goto out;
return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer,
size);
ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer,
size);
out:
drm_dp_dump_access(aux, DP_AUX_NATIVE_READ, offset, buffer, ret);
return ret;
}
EXPORT_SYMBOL(drm_dp_dpcd_read);
@ -312,8 +330,12 @@ EXPORT_SYMBOL(drm_dp_dpcd_read);
ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
void *buffer, size_t size)
{
return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer,
size);
int ret;
ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer,
size);
drm_dp_dump_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer, ret);
return ret;
}
EXPORT_SYMBOL(drm_dp_dpcd_write);
@ -1087,6 +1109,7 @@ static void drm_dp_aux_crc_work(struct work_struct *work)
void drm_dp_aux_init(struct drm_dp_aux *aux)
{
mutex_init(&aux->hw_mutex);
mutex_init(&aux->cec.lock);
INIT_WORK(&aux->crc_work, drm_dp_aux_crc_work);
aux->ddc.algo = &drm_dp_i2c_algo;

View File

@ -1215,7 +1215,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
port->pdt == DP_PEER_DEVICE_SST_SINK) &&
port->port_num >= DP_MST_LOGICAL_PORT_0) {
port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
drm_mode_connector_set_tile_property(port->connector);
drm_connector_set_tile_property(port->connector);
}
(*mstb->mgr->cbs->register_connector)(port->connector);
}
@ -2559,7 +2559,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
edid = drm_edid_duplicate(port->cached_edid);
else {
edid = drm_get_edid(connector, &port->aux.ddc);
drm_mode_connector_set_tile_property(connector);
drm_connector_set_tile_property(connector);
}
port->has_audio = drm_detect_monitor_audio(edid);
drm_dp_put_port(port);

View File

@ -54,13 +54,14 @@ MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl");
MODULE_DESCRIPTION("DRM shared core routines");
MODULE_LICENSE("GPL and additional rights");
MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n"
"\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n"
"\t\tBit 1 (0x02) will enable DRIVER messages (drm controller code)\n"
"\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n"
"\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n"
"\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n"
"\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n"
"\t\tBit 7 (0x80) will enable LEASE messages (leasing code)");
"\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n"
"\t\tBit 1 (0x02) will enable DRIVER messages (drm controller code)\n"
"\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n"
"\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n"
"\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n"
"\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n"
"\t\tBit 7 (0x80) will enable LEASE messages (leasing code)\n"
"\t\tBit 8 (0x100) will enable DP messages (displayport code)");
module_param_named(debug, drm_debug, int, 0600);
static DEFINE_SPINLOCK(drm_minor_lock);

View File

@ -152,27 +152,27 @@ const struct drm_format_info *__drm_format_info(u32 format)
{ .format = DRM_FORMAT_XBGR8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_RGBX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_BGRX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
{ .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
{ .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 },
{ .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 },
{ .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 },
{ .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 },
{ .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 },
{ .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 },
{ .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 },
{ .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 },
{ .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 },
{ .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 },
{ .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 },
{ .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 },
{ .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 },
{ .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 },
{ .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
{ .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
{ .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
{ .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
{ .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true },
{ .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true },
{ .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
};
unsigned int i;

View File

@ -641,7 +641,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_connector_property_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, DRM_UNLOCKED),

View File

@ -433,8 +433,7 @@ static int set_property_legacy(struct drm_mode_object *obj,
drm_modeset_lock_all(dev);
switch (obj->type) {
case DRM_MODE_OBJECT_CONNECTOR:
ret = drm_mode_connector_set_obj_prop(obj, prop,
prop_value);
ret = drm_connector_set_obj_prop(obj, prop, prop_value);
break;
case DRM_MODE_OBJECT_CRTC:
ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value);

View File

@ -1353,7 +1353,7 @@ void drm_mode_sort(struct list_head *mode_list)
EXPORT_SYMBOL(drm_mode_sort);
/**
* drm_mode_connector_list_update - update the mode list for the connector
* drm_connector_list_update - update the mode list for the connector
* @connector: the connector to update
*
* This moves the modes from the @connector probed_modes list
@ -1363,7 +1363,7 @@ EXPORT_SYMBOL(drm_mode_sort);
* This is just a helper functions doesn't validate any modes itself and also
* doesn't prune any invalid modes. Callers need to do that themselves.
*/
void drm_mode_connector_list_update(struct drm_connector *connector)
void drm_connector_list_update(struct drm_connector *connector)
{
struct drm_display_mode *pmode, *pt;
@ -1412,7 +1412,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector)
}
}
}
EXPORT_SYMBOL(drm_mode_connector_list_update);
EXPORT_SYMBOL(drm_connector_list_update);
/**
* drm_mode_parse_command_line_for_connector - parse command line modeline for connector

View File

@ -9,6 +9,13 @@
#include <drm/drm_panel.h>
#include <drm/drm_of.h>
/**
* DOC: overview
*
* A set of helper functions to aid DRM drivers in parsing standard DT
* properties.
*/
static void drm_release_of(struct device *dev, void *data)
{
of_node_put(data);
@ -94,7 +101,7 @@ EXPORT_SYMBOL_GPL(drm_of_component_match_add);
* drm_of_component_probe - Generic probe function for a component based master
* @dev: master device containing the OF node
* @compare_of: compare function used for matching components
* @master_ops: component master ops to be used
* @m_ops: component master ops to be used
*
* Parse the platform device OF node and bind all the components associated
* with the master. Interface ports are added before the encoders in order to

View File

@ -583,6 +583,52 @@ int drm_plane_check_pixel_format(struct drm_plane *plane,
return 0;
}
static int __setplane_check(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int32_t crtc_x, int32_t crtc_y,
uint32_t crtc_w, uint32_t crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{
int ret;
/* Check whether this plane is usable on this CRTC */
if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
DRM_DEBUG_KMS("Invalid crtc for plane\n");
return -EINVAL;
}
/* Check whether this plane supports the fb pixel format. */
ret = drm_plane_check_pixel_format(plane, fb->format->format,
fb->modifier);
if (ret) {
struct drm_format_name_buf format_name;
DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n",
drm_get_format_name(fb->format->format,
&format_name),
fb->modifier);
return ret;
}
/* Give drivers some help against integer overflows */
if (crtc_w > INT_MAX ||
crtc_x > INT_MAX - (int32_t) crtc_w ||
crtc_h > INT_MAX ||
crtc_y > INT_MAX - (int32_t) crtc_h) {
DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
crtc_w, crtc_h, crtc_x, crtc_y);
return -ERANGE;
}
ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb);
if (ret)
return ret;
return 0;
}
/*
* __setplane_internal - setplane handler for internal callers
*
@ -603,6 +649,8 @@ static int __setplane_internal(struct drm_plane *plane,
{
int ret = 0;
WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
/* No fb means shut it down */
if (!fb) {
plane->old_fb = plane->fb;
@ -616,37 +664,9 @@ static int __setplane_internal(struct drm_plane *plane,
goto out;
}
/* Check whether this plane is usable on this CRTC */
if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
DRM_DEBUG_KMS("Invalid crtc for plane\n");
ret = -EINVAL;
goto out;
}
/* Check whether this plane supports the fb pixel format. */
ret = drm_plane_check_pixel_format(plane, fb->format->format,
fb->modifier);
if (ret) {
struct drm_format_name_buf format_name;
DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n",
drm_get_format_name(fb->format->format,
&format_name),
fb->modifier);
goto out;
}
/* Give drivers some help against integer overflows */
if (crtc_w > INT_MAX ||
crtc_x > INT_MAX - (int32_t) crtc_w ||
crtc_h > INT_MAX ||
crtc_y > INT_MAX - (int32_t) crtc_h) {
DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
crtc_w, crtc_h, crtc_x, crtc_y);
ret = -ERANGE;
goto out;
}
ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb);
ret = __setplane_check(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h);
if (ret)
goto out;
@ -655,11 +675,9 @@ static int __setplane_internal(struct drm_plane *plane,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h, ctx);
if (!ret) {
if (!plane->state) {
plane->crtc = crtc;
plane->fb = fb;
drm_framebuffer_get(plane->fb);
}
plane->crtc = crtc;
plane->fb = fb;
drm_framebuffer_get(plane->fb);
} else {
plane->old_fb = NULL;
}
@ -672,6 +690,41 @@ out:
return ret;
}
static int __setplane_atomic(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int32_t crtc_x, int32_t crtc_y,
uint32_t crtc_w, uint32_t crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h,
struct drm_modeset_acquire_ctx *ctx)
{
int ret;
WARN_ON(!drm_drv_uses_atomic_modeset(plane->dev));
/* No fb means shut it down */
if (!fb)
return plane->funcs->disable_plane(plane, ctx);
/*
* FIXME: This is redundant with drm_atomic_plane_check(),
* but the legacy cursor/"async" .update_plane() tricks
* don't call that so we still need this here. Should remove
* this when all .update_plane() implementations have been
* fixed to call drm_atomic_plane_check().
*/
ret = __setplane_check(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h);
if (ret)
return ret;
return plane->funcs->update_plane(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h, ctx);
}
static int setplane_internal(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
@ -689,9 +742,15 @@ retry:
ret = drm_modeset_lock_all_ctx(plane->dev, &ctx);
if (ret)
goto fail;
ret = __setplane_internal(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h, &ctx);
if (drm_drv_uses_atomic_modeset(plane->dev))
ret = __setplane_atomic(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h, &ctx);
else
ret = __setplane_internal(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h, &ctx);
fail:
if (ret == -EDEADLK) {
@ -823,9 +882,14 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
src_h = fb->height << 16;
}
ret = __setplane_internal(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
0, 0, src_w, src_h, ctx);
if (drm_drv_uses_atomic_modeset(dev))
ret = __setplane_atomic(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
0, 0, src_w, src_h, ctx);
else
ret = __setplane_internal(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
0, 0, src_w, src_h, ctx);
if (fb)
drm_framebuffer_put(fb);

View File

@ -360,7 +360,7 @@ EXPORT_SYMBOL(drm_helper_probe_detect);
* using the VESA GTF/CVT formulas.
*
* 3. Modes are moved from the probed_modes list to the modes list. Potential
* duplicates are merged together (see drm_mode_connector_list_update()).
* duplicates are merged together (see drm_connector_list_update()).
* After this step the probed_modes list will be empty again.
*
* 4. Any non-stale mode on the modes list then undergoes validation
@ -472,7 +472,7 @@ retry:
if (connector->status == connector_status_disconnected) {
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
connector->base.id, connector->name);
drm_mode_connector_update_edid_property(connector, NULL);
drm_connector_update_edid_property(connector, NULL);
verbose_prune = false;
goto prune;
}
@ -485,7 +485,7 @@ retry:
if (count == 0)
goto prune;
drm_mode_connector_list_update(connector);
drm_connector_list_update(connector);
if (connector->interlace_allowed)
mode_flags |= DRM_MODE_FLAG_INTERLACE;

View File

@ -287,7 +287,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
if (ret || !connector)
return ret;
return drm_mode_connector_attach_encoder(connector, encoder);
return drm_connector_attach_encoder(connector, encoder);
}
EXPORT_SYMBOL(drm_simple_display_pipe_init);

View File

@ -25,8 +25,8 @@
*
* * Writeback connectors don't provide a way to output visually to the user.
*
* * Writeback connectors should always report as "disconnected" (so that
* clients which don't understand them will ignore them).
* * Writeback connectors are visible to userspace only when the client sets
* DRM_CLIENT_CAP_WRITEBACK_CONNECTORS.
*
* * Writeback connectors don't have EDID.
*
@ -202,7 +202,7 @@ int drm_writeback_connector_init(struct drm_device *dev,
if (ret)
goto connector_fail;
ret = drm_mode_connector_attach_encoder(connector,
ret = drm_connector_attach_encoder(connector,
&wb_connector->encoder);
if (ret)
goto attach_fail;

View File

@ -113,7 +113,7 @@ static int exynos_dpi_create_connector(struct drm_encoder *encoder)
}
drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -1479,7 +1479,7 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
connector->status = connector_status_disconnected;
drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -319,7 +319,7 @@ static int vidi_get_modes(struct drm_connector *connector)
return -ENOMEM;
}
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
return drm_add_edid_modes(connector, edid);
}
@ -344,7 +344,7 @@ static int vidi_create_connector(struct drm_encoder *encoder)
}
drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -888,7 +888,7 @@ static int hdmi_get_modes(struct drm_connector *connector)
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
edid->width_cm, edid->height_cm);
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
cec_notifier_set_phys_addr_from_edid(hdata->notifier, edid);
ret = drm_add_edid_modes(connector, edid);
@ -951,7 +951,7 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
}
drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
if (hdata->bridge) {
ret = drm_bridge_attach(encoder, hdata->bridge, NULL);

View File

@ -117,7 +117,7 @@ static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
if (ret < 0)
goto err_cleanup;
ret = drm_mode_connector_attach_encoder(connector, encoder);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret < 0)
goto err_sysfs;

View File

@ -1770,7 +1770,7 @@ static int cdv_intel_dp_get_modes(struct drm_connector *connector)
edid = drm_get_edid(connector, &intel_dp->adapter);
if (edid) {
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
}

View File

@ -216,7 +216,7 @@ static int cdv_hdmi_get_modes(struct drm_connector *connector)
edid = drm_get_edid(connector, &gma_encoder->i2c_bus->adapter);
if (edid) {
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
}

View File

@ -665,7 +665,7 @@ void gma_connector_attach_encoder(struct gma_connector *connector,
struct gma_encoder *encoder)
{
connector->encoder = encoder;
drm_mode_connector_attach_encoder(&connector->base,
drm_connector_attach_encoder(&connector->base,
&encoder->base);
}

View File

@ -34,7 +34,7 @@ struct vbt_header {
u8 reserved0;
u32 bdb_offset; /**< from beginning of VBT */
u32 aim_offset[4]; /**< from beginning of VBT */
} __attribute__((packed));
} __packed;
struct bdb_header {
@ -61,7 +61,7 @@ struct vbios_data {
u8 rsvd4; /* popup memory size */
u8 resize_pci_bios;
u8 rsvd5; /* is crt already on ddc2 */
} __attribute__((packed));
} __packed;
/*
* There are several types of BIOS data blocks (BDBs), each block has
@ -133,7 +133,7 @@ struct bdb_general_features {
u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */
u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */
u8 rsvd11:3; /* finish byte */
} __attribute__((packed));
} __packed;
/* pre-915 */
#define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */
@ -213,7 +213,7 @@ struct child_device_config {
u8 dvo2_wiring;
u16 extended_type;
u8 dvo_function;
} __attribute__((packed));
} __packed;
struct bdb_general_definitions {
@ -256,7 +256,7 @@ struct bdb_lvds_options {
u8 lvds_edid:1;
u8 rsvd2:1;
u8 rsvd4;
} __attribute__((packed));
} __packed;
struct bdb_lvds_backlight {
u8 type:2;
@ -268,7 +268,7 @@ struct bdb_lvds_backlight {
u8 i2caddr;
u8 brightnesscmd;
/*FIXME: more...*/
} __attribute__((packed));
} __packed;
/* LFP pointer table contains entries to the struct below */
struct bdb_lvds_lfp_data_ptr {
@ -278,12 +278,12 @@ struct bdb_lvds_lfp_data_ptr {
u8 dvo_table_size;
u16 panel_pnp_id_offset;
u8 pnp_table_size;
} __attribute__((packed));
} __packed;
struct bdb_lvds_lfp_data_ptrs {
u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
struct bdb_lvds_lfp_data_ptr ptr[16];
} __attribute__((packed));
} __packed;
/* LFP data has 3 blocks per entry */
struct lvds_fp_timing {
@ -300,7 +300,7 @@ struct lvds_fp_timing {
u32 pfit_reg;
u32 pfit_reg_val;
u16 terminator;
} __attribute__((packed));
} __packed;
struct lvds_dvo_timing {
u16 clock; /**< In 10khz */
@ -328,7 +328,7 @@ struct lvds_dvo_timing {
u8 vsync_positive:1;
u8 hsync_positive:1;
u8 rsvd2:1;
} __attribute__((packed));
} __packed;
struct lvds_pnp_id {
u16 mfg_name;
@ -336,17 +336,17 @@ struct lvds_pnp_id {
u32 serial;
u8 mfg_week;
u8 mfg_year;
} __attribute__((packed));
} __packed;
struct bdb_lvds_lfp_data_entry {
struct lvds_fp_timing fp_timing;
struct lvds_dvo_timing dvo_timing;
struct lvds_pnp_id pnp_id;
} __attribute__((packed));
} __packed;
struct bdb_lvds_lfp_data {
struct bdb_lvds_lfp_data_entry data[16];
} __attribute__((packed));
} __packed;
struct aimdb_header {
char signature[16];
@ -354,12 +354,12 @@ struct aimdb_header {
u16 aimdb_version;
u16 aimdb_header_size;
u16 aimdb_size;
} __attribute__((packed));
} __packed;
struct aimdb_block {
u8 aimdb_id;
u16 aimdb_size;
} __attribute__((packed));
} __packed;
struct vch_panel_data {
u16 fp_timing_offset;
@ -370,12 +370,12 @@ struct vch_panel_data {
u8 text_fitting_size;
u16 graphics_fitting_offset;
u8 graphics_fitting_size;
} __attribute__((packed));
} __packed;
struct vch_bdb_22 {
struct aimdb_block aimdb_block;
struct vch_panel_data panels[16];
} __attribute__((packed));
} __packed;
struct bdb_sdvo_lvds_options {
u8 panel_backlight;
@ -391,7 +391,7 @@ struct bdb_sdvo_lvds_options {
u8 panel_misc_bits_2;
u8 panel_misc_bits_3;
u8 panel_misc_bits_4;
} __attribute__((packed));
} __packed;
#define BDB_DRIVER_FEATURE_NO_LVDS 0
#define BDB_DRIVER_FEATURE_INT_LVDS 1
@ -436,7 +436,7 @@ struct bdb_driver_features {
u8 hdmi_termination;
u8 custom_vbt_version;
} __attribute__((packed));
} __packed;
#define EDP_18BPP 0
#define EDP_24BPP 1

View File

@ -999,7 +999,7 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
p_funcs->encoder_helper_funcs);
/*attach to given connector*/
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
/*set possible crtcs and clones*/
if (dsi_connector->pipe) {

View File

@ -578,7 +578,7 @@ static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
}
if (edid) {
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
}
return ret;

View File

@ -376,7 +376,7 @@ void oaktrail_lvds_init(struct drm_device *dev,
* preferred mode is the right one.
*/
if (edid) {
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
drm_add_edid_modes(connector, edid);
kfree(edid);

View File

@ -66,7 +66,7 @@ int psb_intel_ddc_get_modes(struct drm_connector *connector,
edid = drm_get_edid(connector, adapter);
if (edid) {
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
}

View File

@ -1472,7 +1472,7 @@ static void psb_intel_sdvo_get_ddc_modes(struct drm_connector *connector)
bool connector_is_digital = !!IS_TMDS(psb_intel_sdvo_connector);
if (connector_is_digital == monitor_is_digital) {
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
drm_add_edid_modes(connector, edid);
}

View File

@ -133,7 +133,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)
}
drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -1243,7 +1243,7 @@ static int tda998x_connector_get_modes(struct drm_connector *connector)
return 0;
}
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
n = drm_add_edid_modes(connector, edid);
kfree(edid);
@ -1301,7 +1301,7 @@ static int tda998x_connector_init(struct tda998x_priv *priv,
if (ret)
return ret;
drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder);
drm_connector_attach_encoder(&priv->connector, &priv->encoder);
return 0;
}

View File

@ -3657,7 +3657,7 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format);
if (intel_format_is_yuv(fb->format->format)) {
if (fb->format->is_yuv) {
if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
else
@ -15933,8 +15933,7 @@ void intel_connector_attach_encoder(struct intel_connector *connector,
struct intel_encoder *encoder)
{
connector->encoder = encoder;
drm_mode_connector_attach_encoder(&connector->base,
&encoder->base);
drm_connector_attach_encoder(&connector->base, &encoder->base);
}
/*

View File

@ -4487,6 +4487,9 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
}
/* Handle CEC interrupts, if any */
drm_dp_cec_irq(&intel_dp->aux);
/* defer to the hotplug work for link retraining if needed */
if (intel_dp_needs_link_retrain(intel_dp))
return false;
@ -4803,6 +4806,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
intel_connector->detect_edid = edid;
intel_dp->has_audio = drm_detect_monitor_audio(edid);
drm_dp_cec_set_edid(&intel_dp->aux, edid);
}
static void
@ -4810,6 +4814,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
{
struct intel_connector *intel_connector = intel_dp->attached_connector;
drm_dp_cec_unset_edid(&intel_dp->aux);
kfree(intel_connector->detect_edid);
intel_connector->detect_edid = NULL;
@ -4998,6 +5003,7 @@ static int
intel_dp_connector_register(struct drm_connector *connector)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_device *dev = connector->dev;
int ret;
ret = intel_connector_register(connector);
@ -5010,13 +5016,20 @@ intel_dp_connector_register(struct drm_connector *connector)
intel_dp->aux.name, connector->kdev->kobj.name);
intel_dp->aux.dev = connector->kdev;
return drm_dp_aux_register(&intel_dp->aux);
ret = drm_dp_aux_register(&intel_dp->aux);
if (!ret)
drm_dp_cec_register_connector(&intel_dp->aux,
connector->name, dev->dev);
return ret;
}
static void
intel_dp_connector_unregister(struct drm_connector *connector)
{
drm_dp_aux_unregister(&intel_attached_dp(connector)->aux);
struct intel_dp *intel_dp = intel_attached_dp(connector);
drm_dp_cec_unregister_connector(&intel_dp->aux);
drm_dp_aux_unregister(&intel_dp->aux);
intel_connector_unregister(connector);
}
@ -6212,7 +6225,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
edid = drm_get_edid(connector, &intel_dp->aux.ddc);
if (edid) {
if (drm_add_edid_modes(connector, edid)) {
drm_mode_connector_update_edid_property(connector,
drm_connector_update_edid_property(connector,
edid);
} else {
kfree(edid);
@ -6301,8 +6314,8 @@ static void intel_dp_modeset_retry_work_fn(struct work_struct *work)
/* Set connector link status to BAD and send a Uevent to notify
* userspace to do a modeset.
*/
drm_mode_connector_set_link_status_property(connector,
DRM_MODE_LINK_STATUS_BAD);
drm_connector_set_link_status_property(connector,
DRM_MODE_LINK_STATUS_BAD);
mutex_unlock(&connector->dev->mode_config.mutex);
/* Send Hotplug uevent so userspace can reprobe */
drm_kms_helper_hotplug_event(connector->dev);

View File

@ -466,8 +466,7 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
struct drm_encoder *enc =
&intel_dp->mst_encoders[pipe]->base.base;
ret = drm_mode_connector_attach_encoder(&intel_connector->base,
enc);
ret = drm_connector_attach_encoder(&intel_connector->base, enc);
if (ret)
goto err;
}
@ -475,7 +474,7 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0);
ret = drm_mode_connector_set_path_property(connector, pathprop);
ret = drm_connector_set_path_property(connector, pathprop);
if (ret)
goto err;

View File

@ -2072,7 +2072,6 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
/* intel_sprite.c */
bool intel_format_is_yuv(u32 format);
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
int usecs);
struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,
@ -2088,7 +2087,6 @@ void skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc);
bool skl_plane_get_hw_state(struct intel_plane *plane, enum pipe *pipe);
bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
enum pipe pipe, enum plane_id plane_id);
bool intel_format_is_yuv(uint32_t format);
bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
enum pipe pipe, enum plane_id plane_id);

View File

@ -1131,7 +1131,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
intel_gmbus_get_adapter(dev_priv, pin));
if (edid) {
if (drm_add_edid_modes(connector, edid)) {
drm_mode_connector_update_edid_property(connector,
drm_connector_update_edid_property(connector,
edid);
} else {
kfree(edid);

View File

@ -40,7 +40,7 @@ int intel_connector_update_modes(struct drm_connector *connector,
{
int ret;
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
return ret;

View File

@ -1911,7 +1911,7 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
if (edid != NULL) {
if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector),
edid)) {
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
drm_add_edid_modes(connector, edid);
}

View File

@ -41,20 +41,6 @@
#include <drm/i915_drm.h>
#include "i915_drv.h"
bool intel_format_is_yuv(u32 format)
{
switch (format) {
case DRM_FORMAT_YUYV:
case DRM_FORMAT_UYVY:
case DRM_FORMAT_VYUY:
case DRM_FORMAT_YVYU:
case DRM_FORMAT_NV12:
return true;
default:
return false;
}
}
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
int usecs)
{
@ -416,7 +402,7 @@ chv_update_csc(const struct intel_plane_state *plane_state)
const s16 *csc = csc_matrix[plane_state->base.color_encoding];
/* Seems RGB data bypasses the CSC always */
if (!intel_format_is_yuv(fb->format->format))
if (!fb->format->is_yuv)
return;
I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
@ -451,7 +437,7 @@ vlv_update_clrc(const struct intel_plane_state *plane_state)
enum plane_id plane_id = plane->id;
int contrast, brightness, sh_scale, sh_sin, sh_cos;
if (intel_format_is_yuv(fb->format->format) &&
if (fb->format->is_yuv &&
plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
/*
* Expand limited range to full range:
@ -1052,7 +1038,7 @@ intel_check_sprite_plane(struct intel_plane *plane,
src->y1 = src_y << 16;
src->y2 = (src_y + src_h) << 16;
if (intel_format_is_yuv(fb->format->format) &&
if (fb->format->is_yuv &&
fb->format->format != DRM_FORMAT_NV12 &&
(src_x % 2 || src_w % 2)) {
DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",

View File

@ -143,7 +143,7 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc);
if (imx_ldb_ch->edid) {
drm_mode_connector_update_edid_property(connector,
drm_connector_update_edid_property(connector,
imx_ldb_ch->edid);
num_modes = drm_add_edid_modes(connector, imx_ldb_ch->edid);
}
@ -471,8 +471,7 @@ static int imx_ldb_register(struct drm_device *drm,
drm_connector_init(drm, &imx_ldb_ch->connector,
&imx_ldb_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
encoder);
drm_connector_attach_encoder(&imx_ldb_ch->connector, encoder);
}
if (imx_ldb_ch->panel) {

View File

@ -235,7 +235,7 @@ static int imx_tve_connector_get_modes(struct drm_connector *connector)
edid = drm_get_edid(connector, tve->ddc);
if (edid) {
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
}
@ -493,7 +493,7 @@ static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs,
DRM_MODE_CONNECTOR_VGA);
drm_mode_connector_attach_encoder(&tve->connector, &tve->encoder);
drm_connector_attach_encoder(&tve->connector, &tve->encoder);
return 0;
}

View File

@ -63,7 +63,7 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
}
if (imxpd->edid) {
drm_mode_connector_update_edid_property(connector, imxpd->edid);
drm_connector_update_edid_property(connector, imxpd->edid);
num_modes = drm_add_edid_modes(connector, imxpd->edid);
}
@ -197,7 +197,7 @@ static int imx_pd_register(struct drm_device *drm,
return ret;
}
} else {
drm_mode_connector_attach_encoder(&imxpd->connector, encoder);
drm_connector_attach_encoder(&imxpd->connector, encoder);
}
return 0;

View File

@ -782,7 +782,7 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
drm_connector_helper_add(&dsi->conn, &mtk_dsi_connector_helper_funcs);
dsi->conn.dpms = DRM_MODE_DPMS_OFF;
drm_mode_connector_attach_encoder(&dsi->conn, &dsi->encoder);
drm_connector_attach_encoder(&dsi->conn, &dsi->encoder);
if (dsi->panel) {
ret = drm_panel_attach(dsi->panel, &dsi->conn);

View File

@ -1220,7 +1220,7 @@ static int mtk_hdmi_conn_get_modes(struct drm_connector *conn)
hdmi->dvi_mode = !drm_detect_monitor_audio(edid);
drm_mode_connector_update_edid_property(conn, edid);
drm_connector_update_edid_property(conn, edid);
ret = drm_add_edid_modes(conn, edid);
kfree(edid);
@ -1306,7 +1306,7 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
hdmi->conn.interlace_allowed = true;
hdmi->conn.doublescan_allowed = false;
ret = drm_mode_connector_attach_encoder(&hdmi->conn,
ret = drm_connector_attach_encoder(&hdmi->conn,
bridge->encoder);
if (ret) {
dev_err(hdmi->dev,

View File

@ -329,6 +329,12 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
vclk_freq = mode->clock;
if (!vic) {
meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, vclk_freq,
vclk_freq, vclk_freq, false);
return;
}
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
vclk_freq *= 2;
@ -542,10 +548,12 @@ static enum drm_mode_status
dw_hdmi_mode_valid(struct drm_connector *connector,
const struct drm_display_mode *mode)
{
struct meson_drm *priv = connector->dev->dev_private;
unsigned int vclk_freq;
unsigned int venc_freq;
unsigned int hdmi_freq;
int vic = drm_match_cea_mode(mode);
enum drm_mode_status status;
DRM_DEBUG_DRIVER("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
mode->base.id, mode->name, mode->vrefresh, mode->clock,
@ -556,8 +564,11 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
/* Check against non-VIC supported modes */
if (!vic) {
if (!meson_venc_hdmi_supported_mode(mode))
return MODE_BAD;
status = meson_venc_hdmi_supported_mode(mode);
if (status != MODE_OK)
return status;
return meson_vclk_dmt_supported_freq(priv, mode->clock);
/* Check against supported VIC modes */
} else if (!meson_venc_hdmi_supported_vic(vic))
return MODE_BAD;
@ -583,16 +594,11 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__,
vclk_freq, venc_freq, hdmi_freq);
/* Finally filter by configurable vclk frequencies */
/* Finally filter by configurable vclk frequencies for VIC modes */
switch (vclk_freq) {
case 25175:
case 40000:
case 54000:
case 65000:
case 74250:
case 108000:
case 148500:
case 162000:
case 297000:
case 594000:
return MODE_OK;

View File

@ -320,32 +320,23 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
CTS_VDAC_EN, CTS_VDAC_EN);
}
enum {
/* PLL O1 O2 O3 VP DV EN TX */
/* 4320 /4 /4 /1 /5 /1 => /2 /2 */
#define MESON_VCLK_HDMI_ENCI_54000 1
MESON_VCLK_HDMI_ENCI_54000 = 1,
/* 4320 /4 /4 /1 /5 /1 => /1 /2 */
#define MESON_VCLK_HDMI_DDR_54000 2
MESON_VCLK_HDMI_DDR_54000,
/* 2970 /4 /1 /1 /5 /1 => /1 /2 */
#define MESON_VCLK_HDMI_DDR_148500 3
/* 4028 /4 /4 /1 /5 /2 => /1 /1 */
#define MESON_VCLK_HDMI_25175 4
/* 3200 /4 /2 /1 /5 /2 => /1 /1 */
#define MESON_VCLK_HDMI_40000 5
/* 5200 /4 /2 /1 /5 /2 => /1 /1 */
#define MESON_VCLK_HDMI_65000 6
MESON_VCLK_HDMI_DDR_148500,
/* 2970 /2 /2 /2 /5 /1 => /1 /1 */
#define MESON_VCLK_HDMI_74250 7
/* 4320 /4 /1 /1 /5 /2 => /1 /1 */
#define MESON_VCLK_HDMI_108000 8
MESON_VCLK_HDMI_74250,
/* 2970 /1 /2 /2 /5 /1 => /1 /1 */
#define MESON_VCLK_HDMI_148500 9
/* 3240 /2 /1 /1 /5 /2 => /1 /1 */
#define MESON_VCLK_HDMI_162000 10
MESON_VCLK_HDMI_148500,
/* 2970 /1 /1 /1 /5 /2 => /1 /1 */
#define MESON_VCLK_HDMI_297000 11
MESON_VCLK_HDMI_297000,
/* 5940 /1 /1 /2 /5 /1 => /1 /1 */
#define MESON_VCLK_HDMI_594000 12
MESON_VCLK_HDMI_594000
};
struct meson_vclk_params {
unsigned int pll_base_freq;
@ -411,46 +402,6 @@ struct meson_vclk_params {
.vid_pll_div = VID_PLL_DIV_5,
.vclk_div = 1,
},
[MESON_VCLK_HDMI_25175] = {
.pll_base_freq = 4028000,
.pll_od1 = 4,
.pll_od2 = 4,
.pll_od3 = 1,
.vid_pll_div = VID_PLL_DIV_5,
.vclk_div = 2,
},
[MESON_VCLK_HDMI_40000] = {
.pll_base_freq = 3200000,
.pll_od1 = 4,
.pll_od2 = 2,
.pll_od3 = 1,
.vid_pll_div = VID_PLL_DIV_5,
.vclk_div = 2,
},
[MESON_VCLK_HDMI_65000] = {
.pll_base_freq = 5200000,
.pll_od1 = 4,
.pll_od2 = 2,
.pll_od3 = 1,
.vid_pll_div = VID_PLL_DIV_5,
.vclk_div = 2,
},
[MESON_VCLK_HDMI_108000] = {
.pll_base_freq = 4320000,
.pll_od1 = 4,
.pll_od2 = 1,
.pll_od3 = 1,
.vid_pll_div = VID_PLL_DIV_5,
.vclk_div = 2,
},
[MESON_VCLK_HDMI_162000] = {
.pll_base_freq = 3240000,
.pll_od1 = 2,
.pll_od2 = 1,
.pll_od3 = 1,
.vid_pll_div = VID_PLL_DIV_5,
.vclk_div = 2,
},
};
static inline unsigned int pll_od_to_reg(unsigned int od)
@ -470,358 +421,217 @@ static inline unsigned int pll_od_to_reg(unsigned int od)
return 0;
}
void meson_hdmi_pll_set(struct meson_drm *priv,
unsigned int base,
unsigned int od1,
unsigned int od2,
unsigned int od3)
void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
unsigned int frac, unsigned int od1,
unsigned int od2, unsigned int od3)
{
unsigned int val;
if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
switch (base) {
case 2970000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000200 | m);
if (frac)
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2,
0x00004000 | frac);
else
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2,
0x00000000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
/* Enable and unreset */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
0x7 << 28, 0x4 << 28);
/* Enable and unreset */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
0x7 << 28, 0x4 << 28);
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
val, (val & HDMI_PLL_LOCK), 10, 0);
/* div_frac */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
0xFFFF, 0x4e00);
break;
case 3200000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000242);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
/* unreset */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
BIT(28), 0);
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
val, (val & HDMI_PLL_LOCK), 10, 0);
/* div_frac */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
0xFFFF, 0x4aab);
break;
case 3240000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000243);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
/* unreset */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
BIT(28), 0);
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
val, (val & HDMI_PLL_LOCK), 10, 0);
/* div_frac */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
0xFFFF, 0x4800);
break;
case 3865000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000250);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
/* unreset */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
BIT(28), 0);
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
val, (val & HDMI_PLL_LOCK), 10, 0);
/* div_frac */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
0xFFFF, 0x4855);
break;
case 4028000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000253);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
/* unreset */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
BIT(28), 0);
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
val, (val & HDMI_PLL_LOCK), 10, 0);
/* div_frac */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
0xFFFF, 0x4eab);
break;
case 4320000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800025a);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
/* unreset */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
BIT(28), 0);
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
val, (val & HDMI_PLL_LOCK), 10, 0);
break;
case 5940000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800027b);
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
0xFFFF, 0x4c00);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x135c5091);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
/* unreset */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
BIT(28), 0);
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
val, (val & HDMI_PLL_LOCK), 10, 0);
break;
case 5200000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800026c);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x135c5091);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
/* unreset */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
BIT(28), 0);
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
val, (val & HDMI_PLL_LOCK), 10, 0);
break;
};
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
val, (val & HDMI_PLL_LOCK), 10, 0);
} else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
switch (base) {
case 2970000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
break;
case 3200000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000285);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb155);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
break;
case 3240000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000287);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
break;
case 3865000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002a1);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb02b);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
break;
case 4028000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002a7);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb355);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
break;
case 4320000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002b4);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
break;
case 5940000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002f7);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb200);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
break;
case 5200000:
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002d8);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb2ab);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
break;
};
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000200 | m);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000 | frac);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
/* Reset PLL */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
HDMI_PLL_RESET, HDMI_PLL_RESET);
HDMI_PLL_RESET, HDMI_PLL_RESET);
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
HDMI_PLL_RESET, 0);
HDMI_PLL_RESET, 0);
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
(val & HDMI_PLL_LOCK), 10, 0);
};
}
if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
3 << 16, pll_od_to_reg(od1) << 16);
3 << 16, pll_od_to_reg(od1) << 16);
else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
3 << 21, pll_od_to_reg(od1) << 21);
3 << 21, pll_od_to_reg(od1) << 21);
if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
3 << 22, pll_od_to_reg(od2) << 22);
3 << 22, pll_od_to_reg(od2) << 22);
else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
3 << 23, pll_od_to_reg(od2) << 23);
3 << 23, pll_od_to_reg(od2) << 23);
if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
3 << 18, pll_od_to_reg(od3) << 18);
3 << 18, pll_od_to_reg(od3) << 18);
else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
3 << 19, pll_od_to_reg(od3) << 19);
3 << 19, pll_od_to_reg(od3) << 19);
}
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
unsigned int vclk_freq, unsigned int venc_freq,
unsigned int dac_freq, bool hdmi_use_enci)
#define XTAL_FREQ 24000
static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
unsigned int pll_freq)
{
unsigned int freq;
unsigned int hdmi_tx_div;
unsigned int venc_div;
/* The GXBB PLL has a /2 pre-multiplier */
if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
pll_freq /= 2;
return pll_freq / XTAL_FREQ;
}
#define HDMI_FRAC_MAX_GXBB 4096
#define HDMI_FRAC_MAX_GXL 1024
static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
unsigned int m,
unsigned int pll_freq)
{
unsigned int parent_freq = XTAL_FREQ;
unsigned int frac_max = HDMI_FRAC_MAX_GXL;
unsigned int frac_m;
unsigned int frac;
/* The GXBB PLL has a /2 pre-multiplier and a larger FRAC width */
if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
frac_max = HDMI_FRAC_MAX_GXBB;
parent_freq *= 2;
}
/* We can have a perfect match !*/
if (pll_freq / m == parent_freq &&
pll_freq % m == 0)
return 0;
frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
frac_m = m * frac_max;
if (frac_m > frac)
return frac_max;
frac -= frac_m;
return min((u16)frac, (u16)(frac_max - 1));
}
static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
unsigned int m,
unsigned int frac)
{
if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
/* Empiric supported min/max dividers */
if (m < 53 || m > 123)
return false;
if (frac >= HDMI_FRAC_MAX_GXBB)
return false;
} else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
/* Empiric supported min/max dividers */
if (m < 106 || m > 247)
return false;
if (frac >= HDMI_FRAC_MAX_GXL)
return false;
}
return true;
}
static bool meson_hdmi_pll_find_params(struct meson_drm *priv,
unsigned int freq,
unsigned int *m,
unsigned int *frac,
unsigned int *od)
{
/* Cycle from /16 to /2 */
for (*od = 16 ; *od > 1 ; *od >>= 1) {
*m = meson_hdmi_pll_get_m(priv, freq * *od);
if (!*m)
continue;
*frac = meson_hdmi_pll_get_frac(priv, *m, freq * *od);
DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d\n",
freq, *m, *frac, *od);
if (meson_hdmi_pll_validate_params(priv, *m, *frac))
return true;
}
return false;
}
/* pll_freq is the frequency after the OD dividers */
enum drm_mode_status
meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq)
{
unsigned int od, m, frac;
/* In DMT mode, path after PLL is always /10 */
freq *= 10;
if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
return MODE_OK;
return MODE_CLOCK_RANGE;
}
EXPORT_SYMBOL_GPL(meson_vclk_dmt_supported_freq);
/* pll_freq is the frequency after the OD dividers */
static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
unsigned int pll_freq)
{
unsigned int od, m, frac, od1, od2, od3;
if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
od3 = 1;
if (od < 4) {
od1 = 2;
od2 = 1;
} else {
od2 = od / 4;
od1 = od / od2;
}
DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d/%d/%d\n",
pll_freq, m, frac, od1, od2, od3);
meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
if (target == MESON_VCLK_TARGET_CVBS) {
meson_venci_cvbs_clock_config(priv);
return;
}
hdmi_tx_div = vclk_freq / dac_freq;
if (hdmi_tx_div == 0) {
pr_err("Fatal Error, invalid HDMI-TX freq %d\n",
dac_freq);
return;
}
venc_div = vclk_freq / venc_freq;
if (venc_div == 0) {
pr_err("Fatal Error, invalid HDMI venc freq %d\n",
venc_freq);
return;
}
switch (vclk_freq) {
case 54000:
if (hdmi_use_enci)
freq = MESON_VCLK_HDMI_ENCI_54000;
else
freq = MESON_VCLK_HDMI_DDR_54000;
break;
case 25175:
freq = MESON_VCLK_HDMI_25175;
break;
case 40000:
freq = MESON_VCLK_HDMI_40000;
break;
case 65000:
freq = MESON_VCLK_HDMI_65000;
break;
case 74250:
freq = MESON_VCLK_HDMI_74250;
break;
case 108000:
freq = MESON_VCLK_HDMI_108000;
break;
case 148500:
if (dac_freq != 148500)
freq = MESON_VCLK_HDMI_DDR_148500;
else
freq = MESON_VCLK_HDMI_148500;
break;
case 162000:
freq = MESON_VCLK_HDMI_162000;
break;
case 297000:
freq = MESON_VCLK_HDMI_297000;
break;
case 594000:
freq = MESON_VCLK_HDMI_594000;
break;
default:
pr_err("Fatal Error, invalid HDMI vclk freq %d\n",
vclk_freq);
return;
}
DRM_ERROR("Fatal, unable to find parameters for PLL freq %d\n",
pll_freq);
}
static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
unsigned int od1, unsigned int od2, unsigned int od3,
unsigned int vid_pll_div, unsigned int vclk_div,
unsigned int hdmi_tx_div, unsigned int venc_div,
bool hdmi_use_enci)
{
/* Set HDMI-TX sys clock */
regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
CTS_HDMI_SYS_SEL_MASK, 0);
@ -831,19 +641,49 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
/* Set HDMI PLL rate */
meson_hdmi_pll_set(priv, params[freq].pll_base_freq,
params[freq].pll_od1,
params[freq].pll_od2,
params[freq].pll_od3);
if (!od1 && !od2 && !od3) {
meson_hdmi_pll_generic_set(priv, pll_base_freq);
} else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
switch (pll_base_freq) {
case 2970000:
meson_hdmi_pll_set_params(priv, 0x3d, 0xe00,
od1, od2, od3);
break;
case 4320000:
meson_hdmi_pll_set_params(priv, 0x5a, 0,
od1, od2, od3);
break;
case 5940000:
meson_hdmi_pll_set_params(priv, 0x7b, 0xc00,
od1, od2, od3);
break;
}
} else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
switch (pll_base_freq) {
case 2970000:
meson_hdmi_pll_set_params(priv, 0x7b, 0x300,
od1, od2, od3);
break;
case 4320000:
meson_hdmi_pll_set_params(priv, 0xb4, 0,
od1, od2, od3);
break;
case 5940000:
meson_hdmi_pll_set_params(priv, 0xf7, 0x200,
od1, od2, od3);
break;
}
}
/* Setup vid_pll divider */
meson_vid_pll_set(priv, params[freq].vid_pll_div);
meson_vid_pll_set(priv, vid_pll_div);
/* Set VCLK div */
regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
VCLK_SEL_MASK, 0);
regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
VCLK_DIV_MASK, params[freq].vclk_div - 1);
VCLK_DIV_MASK, vclk_div - 1);
/* Set HDMI-TX source */
switch (hdmi_tx_div) {
@ -981,4 +821,80 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
}
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
unsigned int vclk_freq, unsigned int venc_freq,
unsigned int dac_freq, bool hdmi_use_enci)
{
unsigned int freq;
unsigned int hdmi_tx_div;
unsigned int venc_div;
if (target == MESON_VCLK_TARGET_CVBS) {
meson_venci_cvbs_clock_config(priv);
return;
} else if (target == MESON_VCLK_TARGET_DMT) {
/* The DMT clock path is fixed after the PLL:
* - automatic PLL freq + OD management
* - vid_pll_div = VID_PLL_DIV_5
* - vclk_div = 2
* - hdmi_tx_div = 1
* - venc_div = 1
* - encp encoder
*/
meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
VID_PLL_DIV_5, 2, 1, 1, false);
return;
}
hdmi_tx_div = vclk_freq / dac_freq;
if (hdmi_tx_div == 0) {
pr_err("Fatal Error, invalid HDMI-TX freq %d\n",
dac_freq);
return;
}
venc_div = vclk_freq / venc_freq;
if (venc_div == 0) {
pr_err("Fatal Error, invalid HDMI venc freq %d\n",
venc_freq);
return;
}
switch (vclk_freq) {
case 54000:
if (hdmi_use_enci)
freq = MESON_VCLK_HDMI_ENCI_54000;
else
freq = MESON_VCLK_HDMI_DDR_54000;
break;
case 74250:
freq = MESON_VCLK_HDMI_74250;
break;
case 148500:
if (dac_freq != 148500)
freq = MESON_VCLK_HDMI_DDR_148500;
else
freq = MESON_VCLK_HDMI_148500;
break;
case 297000:
freq = MESON_VCLK_HDMI_297000;
break;
case 594000:
freq = MESON_VCLK_HDMI_594000;
break;
default:
pr_err("Fatal Error, invalid HDMI vclk freq %d\n",
vclk_freq);
return;
}
meson_vclk_set(priv, params[freq].pll_base_freq,
params[freq].pll_od1, params[freq].pll_od2,
params[freq].pll_od3, params[freq].vid_pll_div,
params[freq].vclk_div, hdmi_tx_div, venc_div,
hdmi_use_enci);
}
EXPORT_SYMBOL_GPL(meson_vclk_setup);

View File

@ -24,11 +24,15 @@
enum {
MESON_VCLK_TARGET_CVBS = 0,
MESON_VCLK_TARGET_HDMI = 1,
MESON_VCLK_TARGET_DMT = 2,
};
/* 27MHz is the CVBS Pixel Clock */
#define MESON_VCLK_CVBS 27000
enum drm_mode_status
meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq);
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
unsigned int vclk_freq, unsigned int venc_freq,
unsigned int dac_freq, bool hdmi_use_enci);

View File

@ -697,314 +697,6 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_640x480_60 = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
/* video_prog_mode */
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
/* yfp1_htime */
/* yfp2_htime */
.max_pxcnt = 0x31f,
/* hspuls_begin */
/* hspuls_end */
/* hspuls_switch */
/* vspuls_begin */
/* vspuls_end */
/* vspuls_bline */
/* vspuls_eline */
.havon_begin = 0x90,
.havon_end = 0x30f,
.vavon_bline = 0x23,
.vavon_eline = 0x202,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 0,
.hso_end = 0x60,
.vso_begin = 0x1e,
.vso_end = 0x32,
.vso_bline = 0,
.vso_eline = 2,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 0x20c,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_800x600_60 = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
/* video_prog_mode */
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
/* yfp1_htime */
/* yfp2_htime */
.max_pxcnt = 0x41f,
/* hspuls_begin */
/* hspuls_end */
/* hspuls_switch */
/* vspuls_begin */
/* vspuls_end */
/* vspuls_bline */
/* vspuls_eline */
.havon_begin = 0xD8,
.havon_end = 0x3f7,
.vavon_bline = 0x1b,
.vavon_eline = 0x272,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 0,
.hso_end = 0x80,
.vso_begin = 0x1e,
.vso_end = 0x32,
.vso_bline = 0,
.vso_eline = 4,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 0x273,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1024x768_60 = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
/* video_prog_mode */
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
/* yfp1_htime */
/* yfp2_htime */
.max_pxcnt = 1343,
/* hspuls_begin */
/* hspuls_end */
/* hspuls_switch */
/* vspuls_begin */
/* vspuls_end */
/* vspuls_bline */
/* vspuls_eline */
.havon_begin = 296,
.havon_end = 1319,
.vavon_bline = 35,
.vavon_eline = 802,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 0,
.hso_end = 136,
.vso_begin = 30,
.vso_end = 50,
.vso_bline = 0,
.vso_eline = 6,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 805,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1152x864_75 = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
/* video_prog_mode */
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
/* yfp1_htime */
/* yfp2_htime */
.max_pxcnt = 0x63f,
/* hspuls_begin */
/* hspuls_end */
/* hspuls_switch */
/* vspuls_begin */
/* vspuls_end */
/* vspuls_bline */
/* vspuls_eline */
.havon_begin = 0x180,
.havon_end = 0x5ff,
.vavon_bline = 0x23,
.vavon_eline = 0x382,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 0,
.hso_end = 0x80,
.vso_begin = 0x1e,
.vso_end = 0x32,
.vso_bline = 0,
.vso_eline = 3,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 0x383,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1280x1024_60 = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
/* video_prog_mode */
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
/* yfp1_htime */
/* yfp2_htime */
.max_pxcnt = 0x697,
/* hspuls_begin */
/* hspuls_end */
/* hspuls_switch */
/* vspuls_begin */
/* vspuls_end */
/* vspuls_bline */
/* vspuls_eline */
.havon_begin = 0x168,
.havon_end = 0x667,
.vavon_bline = 0x29,
.vavon_eline = 0x428,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 0,
.hso_end = 0x70,
.vso_begin = 0x1e,
.vso_end = 0x32,
.vso_bline = 0,
.vso_eline = 3,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 0x429,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1600x1200_60 = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
/* video_prog_mode */
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
/* yfp1_htime */
/* yfp2_htime */
.max_pxcnt = 0x86f,
/* hspuls_begin */
/* hspuls_end */
/* hspuls_switch */
/* vspuls_begin */
/* vspuls_end */
/* vspuls_bline */
/* vspuls_eline */
.havon_begin = 0x1f0,
.havon_end = 0x82f,
.vavon_bline = 0x31,
.vavon_eline = 0x4e0,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 0,
.hso_end = 0xc0,
.vso_begin = 0x1e,
.vso_end = 0x32,
.vso_bline = 0,
.vso_eline = 3,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 0x4e1,
},
};
struct meson_hdmi_venc_dmt_mode {
struct drm_display_mode drm_mode;
union meson_hdmi_venc_mode *mode;
} meson_hdmi_venc_dmt_modes[] = {
/* 640x480@60Hz */
{
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
752, 800, 0, 480, 490, 492, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
&meson_hdmi_encp_mode_640x480_60,
},
/* 800x600@60Hz */
{
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
968, 1056, 0, 600, 601, 605, 628, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
&meson_hdmi_encp_mode_800x600_60,
},
/* 1024x768@60Hz */
{
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024,
1048, 1184, 1344, 0, 768, 771, 777, 806, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
&meson_hdmi_encp_mode_1024x768_60,
},
/* 1152x864@75Hz */
{
{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152,
1216, 1344, 1600, 0, 864, 865, 868, 900, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
&meson_hdmi_encp_mode_1152x864_75,
},
/* 1280x1024@60Hz */
{
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280,
1328, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
&meson_hdmi_encp_mode_1280x1024_60,
},
/* 1600x1200@60Hz */
{
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600,
1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
&meson_hdmi_encp_mode_1600x1200_60,
},
/* 1920x1080@60Hz */
{
{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920,
2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
&meson_hdmi_encp_mode_1080p60
},
{ }, /* sentinel */
};
struct meson_hdmi_venc_vic_mode {
unsigned int vic;
union meson_hdmi_venc_mode *mode;
@ -1044,17 +736,20 @@ static unsigned long modulo(unsigned long a, unsigned long b)
return a;
}
bool meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode)
enum drm_mode_status
meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode)
{
struct meson_hdmi_venc_dmt_mode *vmode = meson_hdmi_venc_dmt_modes;
if (mode->flags & ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC |
DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))
return MODE_BAD;
while (vmode->mode) {
if (drm_mode_equal(&vmode->drm_mode, mode))
return true;
vmode++;
}
if (mode->hdisplay < 640 || mode->hdisplay > 1920)
return MODE_BAD_HVALUE;
return false;
if (mode->vdisplay < 480 || mode->vdisplay > 1200)
return MODE_BAD_VVALUE;
return MODE_OK;
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_mode);
@ -1072,18 +767,29 @@ bool meson_venc_hdmi_supported_vic(int vic)
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);
static union meson_hdmi_venc_mode
*meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode)
void meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode,
union meson_hdmi_venc_mode *dmt_mode)
{
struct meson_hdmi_venc_dmt_mode *vmode = meson_hdmi_venc_dmt_modes;
memset(dmt_mode, 0, sizeof(*dmt_mode));
while (vmode->mode) {
if (drm_mode_equal(&vmode->drm_mode, mode))
return vmode->mode;
vmode++;
}
return NULL;
dmt_mode->encp.dvi_settings = 0x21;
dmt_mode->encp.video_mode = 0x4040;
dmt_mode->encp.video_mode_adv = 0x18;
dmt_mode->encp.max_pxcnt = mode->htotal - 1;
dmt_mode->encp.havon_begin = mode->htotal - mode->hsync_start;
dmt_mode->encp.havon_end = dmt_mode->encp.havon_begin +
mode->hdisplay - 1;
dmt_mode->encp.vavon_bline = mode->vtotal - mode->vsync_start;
dmt_mode->encp.vavon_eline = dmt_mode->encp.vavon_bline +
mode->vdisplay - 1;
dmt_mode->encp.hso_begin = 0;
dmt_mode->encp.hso_end = mode->hsync_end - mode->hsync_start;
dmt_mode->encp.vso_begin = 30;
dmt_mode->encp.vso_end = 50;
dmt_mode->encp.vso_bline = 0;
dmt_mode->encp.vso_eline = mode->vsync_end - mode->vsync_start;
dmt_mode->encp.vso_eline_present = true;
dmt_mode->encp.max_lncnt = mode->vtotal - 1;
}
static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic)
@ -1120,6 +826,7 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
struct drm_display_mode *mode)
{
union meson_hdmi_venc_mode *vmode = NULL;
union meson_hdmi_venc_mode vmode_dmt;
bool use_enci = false;
bool venc_repeat = false;
bool hdmi_repeat = false;
@ -1147,14 +854,17 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
unsigned int sof_lines;
unsigned int vsync_lines;
if (meson_venc_hdmi_supported_vic(vic))
if (meson_venc_hdmi_supported_vic(vic)) {
vmode = meson_venc_hdmi_get_vic_vmode(vic);
else
vmode = meson_venc_hdmi_get_dmt_vmode(mode);
if (!vmode) {
dev_err(priv->dev, "%s: Fatal Error, unsupported mode "
DRM_MODE_FMT "\n", __func__, DRM_MODE_ARG(mode));
return;
if (!vmode) {
dev_err(priv->dev, "%s: Fatal Error, unsupported mode "
DRM_MODE_FMT "\n", __func__,
DRM_MODE_ARG(mode));
return;
}
} else {
meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
vmode = &vmode_dmt;
}
/* Use VENCI for 480i and 576i and double HDMI pixels */

View File

@ -58,7 +58,8 @@ struct meson_cvbs_enci_mode {
};
/* HDMI Clock parameters */
bool meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode);
enum drm_mode_status
meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode);
bool meson_venc_hdmi_supported_vic(int vic);
bool meson_venc_hdmi_venc_repeat(int vic);

View File

@ -282,7 +282,7 @@ int meson_venc_cvbs_create(struct meson_drm *priv)
encoder->possible_crtcs = BIT(0);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -1553,7 +1553,7 @@ static int mga_vga_get_modes(struct drm_connector *connector)
edid = drm_get_edid(connector, &mga_connector->i2c->adapter);
if (edid) {
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
}
@ -1747,7 +1747,7 @@ int mgag200_modeset_init(struct mga_device *mdev)
return -1;
}
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
ret = mgag200_fbdev_init(mdev);
if (ret) {

View File

@ -132,7 +132,7 @@ struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev,
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return connector;
}

View File

@ -393,7 +393,7 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
ret = dsi_dual_connector_tile_init(connector, id);
if (ret)
return ret;
ret = drm_mode_connector_set_tile_property(connector);
ret = drm_connector_set_tile_property(connector);
if (ret) {
pr_err("%s: set tile property failed, %d\n",
__func__, ret);
@ -684,7 +684,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
drm_mode_connector_attach_encoder(connector, msm_dsi->encoder);
drm_connector_attach_encoder(connector, msm_dsi->encoder);
return connector;
}

View File

@ -56,7 +56,7 @@ static int edp_connector_get_modes(struct drm_connector *connector)
if (ret)
return ret;
drm_mode_connector_update_edid_property(connector, drm_edid);
drm_connector_update_edid_property(connector, drm_edid);
if (drm_edid)
ret = drm_add_edid_modes(connector, drm_edid);
@ -134,7 +134,7 @@ struct drm_connector *msm_edp_connector_init(struct msm_edp *edp)
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
drm_mode_connector_attach_encoder(connector, edp->encoder);
drm_connector_attach_encoder(connector, edp->encoder);
return connector;
}

View File

@ -392,7 +392,7 @@ static int msm_hdmi_connector_get_modes(struct drm_connector *connector)
hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
drm_mode_connector_update_edid_property(connector, edid);
drm_connector_update_edid_property(connector, edid);
if (edid) {
ret = drm_add_edid_modes(connector, edid);
@ -477,7 +477,7 @@ struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
return ERR_PTR(ret);
}
drm_mode_connector_attach_encoder(connector, hdmi->encoder);
drm_connector_attach_encoder(connector, hdmi->encoder);
return connector;
}

View File

@ -556,6 +556,6 @@ nv04_dac_create(struct drm_connector *connector, struct dcb_output *entry)
encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0;
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -716,6 +716,6 @@ nv04_dfp_create(struct drm_connector *connector, struct dcb_output *entry)
entry->location != DCB_LOC_ON_CHIP)
nv04_tmds_slave_init(encoder);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -244,7 +244,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
/* Attach it to the specified connector. */
get_slave_funcs(encoder)->create_resources(encoder, connector);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;

View File

@ -821,6 +821,6 @@ nv17_tv_create(struct drm_connector *connector, struct dcb_output *entry)
encoder->possible_clones = 0;
nv17_tv_create_resources(encoder, connector);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -449,7 +449,7 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe)
"dac-%04x-%04x", dcbe->hasht, dcbe->hashm);
drm_encoder_helper_add(encoder, &nv50_dac_help);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}
@ -875,7 +875,7 @@ nv50_mstc_get_modes(struct drm_connector *connector)
int ret = 0;
mstc->edid = drm_dp_mst_get_edid(&mstc->connector, mstc->port->mgr, mstc->port);
drm_mode_connector_update_edid_property(&mstc->connector, mstc->edid);
drm_connector_update_edid_property(&mstc->connector, mstc->edid);
if (mstc->edid)
ret = drm_add_edid_modes(&mstc->connector, mstc->edid);
@ -952,11 +952,11 @@ nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port,
nouveau_conn_attach_properties(&mstc->connector);
for (i = 0; i < ARRAY_SIZE(mstm->msto) && mstm->msto[i]; i++)
drm_mode_connector_attach_encoder(&mstc->connector, &mstm->msto[i]->encoder);
drm_connector_attach_encoder(&mstc->connector, &mstm->msto[i]->encoder);
drm_object_attach_property(&mstc->connector.base, dev->mode_config.path_property, 0);
drm_object_attach_property(&mstc->connector.base, dev->mode_config.tile_property, 0);
drm_mode_connector_set_path_property(&mstc->connector, path);
drm_connector_set_path_property(&mstc->connector, path);
return 0;
}
@ -1443,7 +1443,7 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
"sor-%04x-%04x", dcbe->hasht, dcbe->hashm);
drm_encoder_helper_add(encoder, &nv50_sor_help);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
if (dcbe->type == DCB_OUTPUT_DP) {
struct nv50_disp *disp = nv50_disp(encoder->dev);
@ -1601,7 +1601,7 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
"pior-%04x-%04x", dcbe->hasht, dcbe->hashm);
drm_encoder_helper_add(encoder, &nv50_pior_help);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
return 0;
}

View File

@ -550,7 +550,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
/* Cleanup the previous EDID block. */
if (nv_connector->edid) {
drm_mode_connector_update_edid_property(connector, NULL);
drm_connector_update_edid_property(connector, NULL);
kfree(nv_connector->edid);
nv_connector->edid = NULL;
}
@ -575,7 +575,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
else
nv_connector->edid = drm_get_edid(connector, i2c);
drm_mode_connector_update_edid_property(connector,
drm_connector_update_edid_property(connector,
nv_connector->edid);
if (!nv_connector->edid) {
NV_ERROR(drm, "DDC responded, but no EDID for %s\n",
@ -657,7 +657,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
/* Cleanup the previous EDID block. */
if (nv_connector->edid) {
drm_mode_connector_update_edid_property(connector, NULL);
drm_connector_update_edid_property(connector, NULL);
kfree(nv_connector->edid);
nv_connector->edid = NULL;
}
@ -721,7 +721,7 @@ out:
status = connector_status_unknown;
#endif
drm_mode_connector_update_edid_property(connector, nv_connector->edid);
drm_connector_update_edid_property(connector, nv_connector->edid);
nouveau_connector_set_encoder(connector, nv_encoder);
return status;
}

View File

@ -126,14 +126,14 @@ static int omap_connector_get_modes(struct drm_connector *connector)
if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) &&
drm_edid_is_valid(edid)) {
drm_mode_connector_update_edid_property(
drm_connector_update_edid_property(
connector, edid);
n = drm_add_edid_modes(connector, edid);
omap_connector->hdmi_mode =
drm_detect_hdmi_monitor(edid);
} else {
drm_mode_connector_update_edid_property(
drm_connector_update_edid_property(
connector, NULL);
}

View File

@ -274,7 +274,7 @@ static int omap_modeset_init(struct drm_device *dev)
if (IS_ERR(crtc))
return PTR_ERR(crtc);
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
encoder->possible_crtcs = (1 << crtc_idx);
priv->crtcs[priv->num_crtcs++] = crtc;

View File

@ -252,7 +252,7 @@ static int panel_simple_get_modes(struct drm_panel *panel)
/* probe EDID if a DDC bus is available */
if (p->ddc) {
struct edid *edid = drm_get_edid(panel->connector, p->ddc);
drm_mode_connector_update_edid_property(panel->connector, edid);
drm_connector_update_edid_property(panel->connector, edid);
if (edid) {
num += drm_add_edid_modes(panel->connector, edid);
kfree(edid);

View File

@ -63,7 +63,7 @@ pl111_mode_valid(struct drm_crtc *crtc,
* We use the pixelclock to also account for interlaced modes, the
* resulting bandwidth is in bytes per second.
*/
bw = mode->clock * 1000; /* In Hz */
bw = mode->clock * 1000ULL; /* In Hz */
bw = bw * mode->hdisplay * mode->vdisplay * cpp;
bw = div_u64(bw, mode->htotal * mode->vtotal);

View File

@ -304,13 +304,14 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
if (IS_ERR(priv->regs)) {
dev_err(dev, "%s failed mmio\n", __func__);
ret = PTR_ERR(priv->regs);
goto dev_unref;
goto dev_put;
}
/* This may override some variant settings */
ret = pl111_versatile_init(dev, priv);
if (ret)
goto dev_unref;
goto dev_put;
pl111_nomadik_init(dev);
/* turn off interrupts before requesting the irq */
@ -325,16 +326,16 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
ret = pl111_modeset_init(drm);
if (ret != 0)
goto dev_unref;
goto dev_put;
ret = drm_dev_register(drm, 0);
if (ret < 0)
goto dev_unref;
goto dev_put;
return 0;
dev_unref:
drm_dev_unref(drm);
dev_put:
drm_dev_put(drm);
of_reserved_mem_device_release(dev);
return ret;
@ -351,7 +352,7 @@ static int pl111_amba_remove(struct amba_device *amba_dev)
if (priv->panel)
drm_panel_bridge_remove(priv->bridge);
drm_mode_config_cleanup(drm);
drm_dev_unref(drm);
drm_dev_put(drm);
of_reserved_mem_device_release(dev);
return 0;

View File

@ -1086,7 +1086,7 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
/* we get HPD via client monitors config */
connector->polled = DRM_CONNECTOR_POLL_HPD;
encoder->possible_crtcs = 1 << num_output;
drm_mode_connector_attach_encoder(&qxl_output->base,
drm_connector_attach_encoder(&qxl_output->base,
&qxl_output->enc);
drm_encoder_helper_add(encoder, &qxl_enc_helper_funcs);
drm_connector_helper_add(connector, &qxl_connector_helper_funcs);

View File

@ -368,11 +368,11 @@ static int radeon_ddc_get_modes(struct drm_connector *connector)
int ret;
if (radeon_connector->edid) {
drm_mode_connector_update_edid_property(connector, radeon_connector->edid);
drm_connector_update_edid_property(connector, radeon_connector->edid);
ret = drm_add_edid_modes(connector, radeon_connector->edid);
return ret;
}
drm_mode_connector_update_edid_property(connector, NULL);
drm_connector_update_edid_property(connector, NULL);
return 0;
}

View File

@ -195,11 +195,11 @@ static int radeon_dp_mst_get_ddc_modes(struct drm_connector *connector)
radeon_connector->edid = edid;
DRM_DEBUG_KMS("edid retrieved %p\n", edid);
if (radeon_connector->edid) {
drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
drm_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
return ret;
}
drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
drm_connector_update_edid_property(&radeon_connector->base, NULL);
return ret;
}
@ -290,7 +290,7 @@ static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topol
drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0);
drm_mode_connector_set_path_property(connector, pathprop);
drm_connector_set_path_property(connector, pathprop);
return connector;
}

View File

@ -211,7 +211,7 @@ radeon_link_encoder_connector(struct drm_device *dev)
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
radeon_encoder = to_radeon_encoder(encoder);
if (radeon_encoder->devices & radeon_connector->devices) {
drm_mode_connector_attach_encoder(connector, encoder);
drm_connector_attach_encoder(connector, encoder);
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
radeon_encoder_add_backlight(radeon_encoder, connector);
}

Some files were not shown because too many files have changed in this diff Show More