aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/drm_crtc.c368
-rw-r--r--drivers/gpu/drm/drm_drv.c4
-rw-r--r--drivers/gpu/drm/exynos/Kconfig29
-rw-r--r--drivers/gpu/drm/exynos/Makefile6
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_buf.c60
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_core.c7
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c296
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h31
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dmabuf.c26
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c180
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h39
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.c125
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.h12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c81
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c1925
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.h (renamed from drivers/gpu/drm/exynos_tmp/exynos_drm_vidi.h)21
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c1543
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c251
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c547
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.h35
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c1385
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.h (renamed from drivers/gpu/drm/exynos_tmp/exynos_drm_connector.h)17
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_iommu.c212
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_iommu.h47
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.c1638
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.h191
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c246
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.h12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.c751
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.h12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ump.c9
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c29
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c208
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c10
-rw-r--r--drivers/gpu/drm/exynos/regs-fimc.h669
-rw-r--r--drivers/gpu/drm/exynos/regs-gsc.h295
-rw-r--r--drivers/gpu/drm/exynos_tmp/Kconfig46
-rw-r--r--drivers/gpu/drm/exynos_tmp/Makefile20
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_ddc.c57
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_buf.c241
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_buf.h47
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_connector.c357
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_core.c217
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_crtc.c436
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_crtc.h67
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_dmabuf.c288
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_dmabuf.h39
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_drv.c484
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_drv.h335
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_encoder.c445
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_encoder.h52
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_fb.c251
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_fb.h55
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_fbdev.c318
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_fbdev.h37
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_fimd.c1700
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_g2d.c1007
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_g2d.h36
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_gem.c1437
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_gem.h246
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_hdmi.c386
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_hdmi.h77
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_iommu.c329
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_iommu.h79
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_plane.c171
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_plane.h14
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_rotator.c904
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_rotator.h25
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_ump.c151
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_drm_vidi.c680
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_hdmi.c2481
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_hdmi.h37
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_hdmiphy.c58
-rw-r--r--drivers/gpu/drm/exynos_tmp/exynos_mixer.c1109
-rw-r--r--drivers/gpu/drm/exynos_tmp/regs-hdmi.h723
-rw-r--r--drivers/gpu/drm/exynos_tmp/regs-mixer.h141
-rw-r--r--drivers/gpu/drm/exynos_tmp/regs-vp.h91
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c2
-rw-r--r--drivers/gpu/drm/i915/intel_display.c2
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c24
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c11
-rw-r--r--drivers/gpu/drm/radeon/r100.c3
-rw-r--r--drivers/gpu/drm/radeon/rs600.c10
84 files changed, 8342 insertions, 18705 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index aa76700..e8acc19 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -381,6 +381,8 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
if (ret)
goto out;
+ crtc->base.properties = &crtc->properties;
+
list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
dev->mode_config.num_crtc++;
@@ -480,6 +482,7 @@ int drm_connector_init(struct drm_device *dev,
if (ret)
goto out;
+ connector->base.properties = &connector->properties;
connector->dev = dev;
connector->funcs = funcs;
connector->connector_type = connector_type;
@@ -602,6 +605,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
if (ret)
goto out;
+ plane->base.properties = &plane->properties;
plane->dev = dev;
plane->funcs = funcs;
plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
@@ -1421,11 +1425,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
}
connector = obj_to_connector(obj);
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] != 0) {
- props_count++;
- }
- }
+ props_count = connector->properties.count;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] != 0) {
@@ -1478,21 +1478,19 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
copied = 0;
prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr);
prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr);
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] != 0) {
- if (put_user(connector->property_ids[i],
- prop_ptr + copied)) {
- ret = -EFAULT;
- goto out;
- }
+ for (i = 0; i < connector->properties.count; i++) {
+ if (put_user(connector->properties.ids[i],
+ prop_ptr + copied)) {
+ ret = -EFAULT;
+ goto out;
+ }
- if (put_user(connector->property_values[i],
- prop_values + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
+ if (put_user(connector->properties.values[i],
+ prop_values + copied)) {
+ ret = -EFAULT;
+ goto out;
}
+ copied++;
}
}
out_resp->count_props = props_count;
@@ -2712,6 +2710,34 @@ struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
}
EXPORT_SYMBOL(drm_property_create_enum);
+struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
+ int flags, const char *name,
+ const struct drm_prop_enum_list *props,
+ int num_values)
+{
+ struct drm_property *property;
+ int i, ret;
+
+ flags |= DRM_MODE_PROP_BITMASK;
+
+ property = drm_property_create(dev, flags, name, num_values);
+ if (!property)
+ return NULL;
+
+ for (i = 0; i < num_values; i++) {
+ ret = drm_property_add_enum(property, i,
+ props[i].type,
+ props[i].name);
+ if (ret) {
+ drm_property_destroy(dev, property);
+ return NULL;
+ }
+ }
+
+ return property;
+}
+EXPORT_SYMBOL(drm_property_create_bitmask);
+
struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
const char *name,
uint64_t min, uint64_t max)
@@ -2736,7 +2762,14 @@ int drm_property_add_enum(struct drm_property *property, int index,
{
struct drm_property_enum *prop_enum;
- if (!(property->flags & DRM_MODE_PROP_ENUM))
+ if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
+ return -EINVAL;
+
+ /*
+ * Bitmask enum properties have the additional constraint of values
+ * from 0 to 63
+ */
+ if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
return -EINVAL;
if (!list_empty(&property->enum_blob_list)) {
@@ -2780,60 +2813,78 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
}
EXPORT_SYMBOL(drm_property_destroy);
-int drm_connector_attach_property(struct drm_connector *connector,
+void drm_connector_attach_property(struct drm_connector *connector,
struct drm_property *property, uint64_t init_val)
{
- int i;
-
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] == 0) {
- connector->property_ids[i] = property->base.id;
- connector->property_values[i] = init_val;
- break;
- }
- }
-
- if (i == DRM_CONNECTOR_MAX_PROPERTY)
- return -EINVAL;
- return 0;
+ drm_object_attach_property(&connector->base, property, init_val);
}
EXPORT_SYMBOL(drm_connector_attach_property);
int drm_connector_property_set_value(struct drm_connector *connector,
struct drm_property *property, uint64_t value)
{
+ return drm_object_property_set_value(&connector->base, property, value);
+}
+EXPORT_SYMBOL(drm_connector_property_set_value);
+
+int drm_connector_property_get_value(struct drm_connector *connector,
+ struct drm_property *property, uint64_t *val)
+{
+ return drm_object_property_get_value(&connector->base, property, val);
+}
+EXPORT_SYMBOL(drm_connector_property_get_value);
+
+void drm_object_attach_property(struct drm_mode_object *obj,
+ struct drm_property *property,
+ uint64_t init_val)
+{
+ int count = obj->properties->count;
+
+ if (count == DRM_OBJECT_MAX_PROPERTY) {
+ WARN(1, "Failed to attach object property (type: 0x%x). Please "
+ "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
+ "you see this message on the same object type.\n",
+ obj->type);
+ return;
+ }
+
+ obj->properties->ids[count] = property->base.id;
+ obj->properties->values[count] = init_val;
+ obj->properties->count++;
+}
+EXPORT_SYMBOL(drm_object_attach_property);
+
+int drm_object_property_set_value(struct drm_mode_object *obj,
+ struct drm_property *property, uint64_t val)
+{
int i;
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] == property->base.id) {
- connector->property_values[i] = value;
- break;
+ for (i = 0; i < obj->properties->count; i++) {
+ if (obj->properties->ids[i] == property->base.id) {
+ obj->properties->values[i] = val;
+ return 0;
}
}
- if (i == DRM_CONNECTOR_MAX_PROPERTY)
- return -EINVAL;
- return 0;
+ return -EINVAL;
}
-EXPORT_SYMBOL(drm_connector_property_set_value);
+EXPORT_SYMBOL(drm_object_property_set_value);
-int drm_connector_property_get_value(struct drm_connector *connector,
+int drm_object_property_get_value(struct drm_mode_object *obj,
struct drm_property *property, uint64_t *val)
{
int i;
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] == property->base.id) {
- *val = connector->property_values[i];
- break;
+ for (i = 0; i < obj->properties->count; i++) {
+ if (obj->properties->ids[i] == property->base.id) {
+ *val = obj->properties->values[i];
+ return 0;
}
}
- if (i == DRM_CONNECTOR_MAX_PROPERTY)
- return -EINVAL;
- return 0;
+ return -EINVAL;
}
-EXPORT_SYMBOL(drm_connector_property_get_value);
+EXPORT_SYMBOL(drm_object_property_get_value);
int drm_mode_getproperty_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
@@ -2864,7 +2915,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
}
property = obj_to_property(obj);
- if (property->flags & DRM_MODE_PROP_ENUM) {
+ if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
list_for_each_entry(prop_enum, &property->enum_blob_list, head)
enum_count++;
} else if (property->flags & DRM_MODE_PROP_BLOB) {
@@ -2889,7 +2940,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
}
out_resp->count_values = value_count;
- if (property->flags & DRM_MODE_PROP_ENUM) {
+ if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
copied = 0;
enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
@@ -3035,75 +3086,202 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
}
EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
+static bool drm_property_change_is_valid(struct drm_property *property,
+ __u64 value)
+{
+ if (property->flags & DRM_MODE_PROP_IMMUTABLE)
+ return false;
+ if (property->flags & DRM_MODE_PROP_RANGE) {
+ if (value < property->values[0] || value > property->values[1])
+ return false;
+ return true;
+ } else if (property->flags & DRM_MODE_PROP_BITMASK) {
+ int i;
+ __u64 valid_mask = 0;
+ for (i = 0; i < property->num_values; i++)
+ valid_mask |= (1ULL << property->values[i]);
+ return !(value & ~valid_mask);
+ } else {
+ int i;
+ for (i = 0; i < property->num_values; i++)
+ if (property->values[i] == value)
+ return true;
+ return false;
+ }
+}
+
int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
- struct drm_mode_connector_set_property *out_resp = data;
- struct drm_mode_object *obj;
- struct drm_property *property;
- struct drm_connector *connector;
+ struct drm_mode_connector_set_property *conn_set_prop = data;
+ struct drm_mode_obj_set_property obj_set_prop = {
+ .value = conn_set_prop->value,
+ .prop_id = conn_set_prop->prop_id,
+ .obj_id = conn_set_prop->connector_id,
+ .obj_type = DRM_MODE_OBJECT_CONNECTOR
+ };
+
+ /* It does all the locking and checking we need */
+ return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
+}
+
+static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
+ struct drm_property *property,
+ uint64_t value)
+{
+ int ret = -EINVAL;
+ struct drm_connector *connector = obj_to_connector(obj);
+
+ /* Do DPMS ourselves */
+ if (property == connector->dev->mode_config.dpms_property) {
+ if (connector->funcs->dpms)
+ (*connector->funcs->dpms)(connector, (int)value);
+ ret = 0;
+ } else if (connector->funcs->set_property)
+ ret = connector->funcs->set_property(connector, property, value);
+
+ /* store the property value if successful */
+ if (!ret)
+ drm_connector_property_set_value(connector, property, value);
+ return ret;
+}
+
+static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
+ struct drm_property *property,
+ uint64_t value)
+{
+ int ret = -EINVAL;
+ struct drm_crtc *crtc = obj_to_crtc(obj);
+
+ if (crtc->funcs->set_property)
+ ret = crtc->funcs->set_property(crtc, property, value);
+ if (!ret)
+ drm_object_property_set_value(obj, property, value);
+
+ return ret;
+}
+
+static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj,
+ struct drm_property *property,
+ uint64_t value)
+{
int ret = -EINVAL;
+ struct drm_plane *plane = obj_to_plane(obj);
+
+ if (plane->funcs->set_property)
+ ret = plane->funcs->set_property(plane, property, value);
+ if (!ret)
+ drm_object_property_set_value(obj, property, value);
+
+ return ret;
+}
+
+int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_mode_obj_get_properties *arg = data;
+ struct drm_mode_object *obj;
+ int ret = 0;
int i;
+ int copied = 0;
+ int props_count = 0;
+ uint32_t __user *props_ptr;
+ uint64_t __user *prop_values_ptr;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR);
+ obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
if (!obj) {
+ ret = -EINVAL;
+ goto out;
+ }
+ if (!obj->properties) {
+ ret = -EINVAL;
goto out;
}
- connector = obj_to_connector(obj);
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] == out_resp->prop_id)
- break;
+ props_count = obj->properties->count;
+
+ /* This ioctl is called twice, once to determine how much space is
+ * needed, and the 2nd time to fill it. */
+ if ((arg->count_props >= props_count) && props_count) {
+ copied = 0;
+ props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
+ prop_values_ptr = (uint64_t __user *)(unsigned long)
+ (arg->prop_values_ptr);
+ for (i = 0; i < props_count; i++) {
+ if (put_user(obj->properties->ids[i],
+ props_ptr + copied)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ if (put_user(obj->properties->values[i],
+ prop_values_ptr + copied)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ copied++;
+ }
}
+ arg->count_props = props_count;
+out:
+ mutex_unlock(&dev->mode_config.mutex);
+ return ret;
+}
+
+int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_mode_obj_set_property *arg = data;
+ struct drm_mode_object *arg_obj;
+ struct drm_mode_object *prop_obj;
+ struct drm_property *property;
+ int ret = -EINVAL;
+ int i;
- if (i == DRM_CONNECTOR_MAX_PROPERTY) {
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+ mutex_lock(&dev->mode_config.mutex);
+
+ arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
+ if (!arg_obj)
+ goto out;
+ if (!arg_obj->properties)
goto out;
- }
- obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
- if (!obj) {
+ for (i = 0; i < arg_obj->properties->count; i++)
+ if (arg_obj->properties->ids[i] == arg->prop_id)
+ break;
+
+ if (i == arg_obj->properties->count)
goto out;
- }
- property = obj_to_property(obj);
- if (property->flags & DRM_MODE_PROP_IMMUTABLE)
+ prop_obj = drm_mode_object_find(dev, arg->prop_id,
+ DRM_MODE_OBJECT_PROPERTY);
+ if (!prop_obj)
goto out;
+ property = obj_to_property(prop_obj);
- if (property->flags & DRM_MODE_PROP_RANGE) {
- if (out_resp->value < property->values[0])
- goto out;
+ if (!drm_property_change_is_valid(property, arg->value))
+ goto out;
- if (out_resp->value > property->values[1])
- goto out;
- } else {
- int found = 0;
- for (i = 0; i < property->num_values; i++) {
- if (property->values[i] == out_resp->value) {
- found = 1;
- break;
- }
- }
- if (!found) {
- goto out;
- }
+ switch (arg_obj->type) {
+ case DRM_MODE_OBJECT_CONNECTOR:
+ ret = drm_mode_connector_set_obj_prop(arg_obj, property,
+ arg->value);
+ break;
+ case DRM_MODE_OBJECT_CRTC:
+ ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
+ break;
+ case DRM_MODE_OBJECT_PLANE:
+ ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value);
+ break;
}
- /* Do DPMS ourselves */
- if (property == connector->dev->mode_config.dpms_property) {
- if (connector->funcs->dpms)
- (*connector->funcs->dpms)(connector, (int) out_resp->value);
- ret = 0;
- } else if (connector->funcs->set_property)
- ret = connector->funcs->set_property(connector, property, out_resp->value);
-
- /* store the property value if successful */
- if (!ret)
- drm_connector_property_set_value(connector, property, out_resp->value);
out:
mutex_unlock(&dev->mode_config.mutex);
return ret;
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 2083180..4ac7199 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -162,7 +162,9 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
};
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 3d002cc..b4ae4c5 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -15,6 +15,12 @@ config DRM_EXYNOS_MEMSIZE
depends on DRM_EXYNOS
default "32768"
+config DRM_EXYNOS_IOMMU
+ bool "GEM IOMMU Support"
+ depends on DRM_EXYNOS
+ help
+ Choose this option if you want to use GEM IOMMU feature for DRM.
+
config DRM_EXYNOS_DMABUF
bool "GEM DMABUF Support"
depends on DRM_EXYNOS
@@ -54,8 +60,29 @@ config DRM_EXYNOS_G2D
help
Choose this option if you want to use Samsung G2D for DRM.
+config DRM_EXYNOS_IPP
+ bool "Samsung DRM IPP"
+ depends on DRM_EXYNOS
+ help
+ This option enables IPP drivers for FIMC, GSC, Rotator.
+ It can support user space ioctl for each devices.
+ ipp operations support rotating and scaling, writeback, flip, output
+ when enable this options.
+
config DRM_EXYNOS_ROTATOR
bool "Samsung DRM Rotator"
- depends on DRM_EXYNOS
+ depends on DRM_EXYNOS_IPP
help
Choose this option if you want to use Samsung Rotator for DRM.
+
+config DRM_EXYNOS_FIMC
+ bool "Samsung DRM FIMC"
+ depends on DRM_EXYNOS_IPP
+ help
+ Choose this option if you want to use Samsung FIMC for DRM.
+
+config DRM_EXYNOS_GSC
+ bool "Samsung DRM GSC"
+ depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5
+ help
+ Choose this option if you want to use Samsung GSC for DRM.
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index f8a88f3..369b3a5 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -7,14 +7,18 @@ ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos \
exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \
exynos_drm_buf.o exynos_drm_ump.o exynos_drm_gem.o \
- exynos_drm_core.o exynos_drm_plane.o exynos_drm_iommu.o
+ exynos_drm_core.o exynos_drm_plane.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o exynos_ddc.o \
exynos_hdmiphy.o exynos_drm_hdmi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o
exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC) += exynos_drm_fimc.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_GSC) += exynos_drm_gsc.o
obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c
index f7bb7be..a0b27d9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_buf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c
@@ -47,7 +47,7 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
return -EINVAL;
}
- if (buf->dma_addr) {
+ if (buf->paddr) {
DRM_DEBUG_KMS("already allocated.\n");
return 0;
}
@@ -78,21 +78,21 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
}
#ifdef CONFIG_CMA
- buf->dma_addr = cma_alloc(dev->dev, "drm", buf->size,
+ buf->paddr = cma_alloc(dev->dev, "drm", buf->size,
buf->page_size);
- if (IS_ERR((void *)buf->dma_addr)) {
+ if (IS_ERR((void *)buf->paddr)) {
DRM_DEBUG_KMS("cma_alloc of size %ld failed\n",
buf->size);
ret = -ENOMEM;
goto err1;
}
- buf->kvaddr = phys_to_virt(buf->dma_addr);
+ buf->kvaddr = phys_to_virt(buf->paddr);
#else
/* align it as page size(page or section) TODO */
buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size,
- &buf->dma_addr, GFP_KERNEL);
+ &buf->paddr, GFP_KERNEL);
if (!buf->kvaddr) {
DRM_ERROR("failed to allocate buffer.\n");
ret = -ENOMEM;
@@ -107,7 +107,7 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
}
sgl = buf->sgt->sgl;
- start_addr = buf->dma_addr;
+ start_addr = buf->paddr;
while (i < npages) {
buf->pages[i] = phys_to_page(start_addr);
@@ -118,20 +118,20 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
i++;
}
- DRM_INFO("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
+ DRM_INFO("vaddr(0x%lx), paddr(0x%lx), size(0x%lx)\n",
(unsigned long)buf->kvaddr,
- (unsigned long)buf->dma_addr,
+ (unsigned long)buf->paddr,
buf->size);
return ret;
err2:
#ifdef CONFIG_CMA
- cma_free(buf->dma_addr);
+ cma_free(buf->paddr);
#else
dma_free_writecombine(dev->dev, buf->size, buf->kvaddr,
- (dma_addr_t)buf->dma_addr);
+ (dma_addr_t)buf->paddr);
#endif
- buf->dma_addr = (dma_addr_t)NULL;
+ buf->paddr = (dma_addr_t)NULL;
err1:
sg_free_table(buf->sgt);
kfree(buf->sgt);
@@ -146,13 +146,6 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
DRM_DEBUG_KMS("%s.\n", __FILE__);
/*
- * now buffer is being shared and it would be released
- * by original owner so ignor free action.
- */
- if (buf->shared || atomic_read(&buf->shared_refcount))
- return;
-
- /*
* release only physically continuous memory and
* non-continuous memory would be released by exynos
* gem framework.
@@ -162,25 +155,36 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
return;
}
- if (!buf->dma_addr) {
- DRM_DEBUG_KMS("dma_addr is invalid.\n");
+ if (!buf->paddr) {
+ DRM_DEBUG_KMS("paddr is invalid.\n");
return;
}
- sg_free_table(buf->sgt);
-
- kfree(buf->sgt);
- buf->sgt = NULL;
+ if (buf->sgt) {
+ sg_free_table(buf->sgt);
+ kfree(buf->sgt);
+ buf->sgt = NULL;
+ }
kfree(buf->pages);
buf->pages = NULL;
+
+ /*
+ * now buffer is being shared and it would be released
+ * by original owner so ignor free action.
+ * this buffer was imported from physical memory to gem directly
+ * and this feature is used temporarily so removed later.
+ */
+ if (buf->shared)
+ return;
+
#ifdef CONFIG_CMA
- cma_free(buf->dma_addr);
+ cma_free(buf->paddr);
#else
dma_free_writecombine(dev->dev, buf->size, buf->kvaddr,
- (dma_addr_t)buf->dma_addr);
+ (dma_addr_t)buf->paddr);
#endif
- buf->dma_addr = (dma_addr_t)NULL;
+ buf->paddr = (dma_addr_t)NULL;
}
struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev,
@@ -221,7 +225,7 @@ int exynos_drm_alloc_buf(struct drm_device *dev,
/*
* allocate memory region and set the memory information
- * to vaddr and dma_addr of a buffer object.
+ * to vaddr and paddr of a buffer object.
*/
if (lowlevel_buffer_allocate(dev, flags, buf) < 0)
return -ENOMEM;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index eaf630d..80cba2f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -33,7 +33,6 @@
#include "exynos_drm_fbdev.h"
static LIST_HEAD(exynos_drm_subdrv_list);
-static struct drm_device *drm_dev;
static int exynos_drm_subdrv_probe(struct drm_device *dev,
struct exynos_drm_subdrv *subdrv)
@@ -95,7 +94,7 @@ static void exynos_drm_subdrv_remove(struct drm_device *dev,
DRM_DEBUG_DRIVER("%s\n", __FILE__);
if (subdrv->remove)
- subdrv->remove(dev);
+ subdrv->remove(dev, subdrv->dev);
if (subdrv->encoder) {
struct drm_encoder *encoder = subdrv->encoder;
@@ -120,8 +119,6 @@ int exynos_drm_device_register(struct drm_device *dev)
if (!dev)
return -EINVAL;
- drm_dev = dev;
-
list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
subdrv->drm_dev = dev;
err = exynos_drm_subdrv_probe(dev, subdrv);
@@ -149,8 +146,6 @@ int exynos_drm_device_unregister(struct drm_device *dev)
list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list)
exynos_drm_subdrv_remove(dev, subdrv);
- drm_dev = NULL;
-
return 0;
}
EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 4afb625..5904c58 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -29,21 +29,23 @@
#include "drmP.h"
#include "drm_crtc_helper.h"
-#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
-#include "exynos_drm_fb.h"
#include "exynos_drm_encoder.h"
-#include "exynos_drm_gem.h"
+#include "exynos_drm_plane.h"
#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\
drm_crtc)
+enum exynos_crtc_mode {
+ CRTC_MODE_NORMAL, /* normal mode */
+ CRTC_MODE_BLANK, /* The private plane of crtc is blank */
+};
+
/*
* Exynos specific crtc structure.
*
* @drm_crtc: crtc object.
- * @overlay: contain information common to display controller and hdmi and
- * contents of this overlay object would be copied to sub driver size.
+ * @drm_plane: pointer of private plane object for this crtc
* @pipe: a crtc index created at load() with a new crtc object creation
* and the crtc object would be set to private->crtc array
* to get a crtc object corresponding to this pipe from private->crtc
@@ -52,115 +54,16 @@
* we can refer to the crtc to current hardware interrupt occured through
* this pipe value.
* @dpms: store the crtc dpms value
+ * @mode: store the crtc mode value
*/
struct exynos_drm_crtc {
struct drm_crtc drm_crtc;
- struct exynos_drm_overlay overlay;
+ struct drm_plane *plane;
unsigned int pipe;
unsigned int dpms;
+ enum exynos_crtc_mode mode;
};
-static void exynos_drm_crtc_apply(struct drm_crtc *crtc)
-{
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- struct exynos_drm_overlay *overlay = &exynos_crtc->overlay;
-
- exynos_drm_fn_encoder(crtc, overlay,
- exynos_drm_encoder_crtc_mode_set);
- exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
- exynos_drm_encoder_crtc_commit);
-}
-
-int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
- struct drm_framebuffer *fb,
- struct drm_display_mode *mode,
- struct exynos_drm_crtc_pos *pos)
-{
- struct exynos_drm_gem_buf *buffer;
- unsigned int actual_w;
- unsigned int actual_h;
- int nr = exynos_drm_format_num_buffers(fb->pixel_format);
- int i;
-
- for (i = 0; i < nr; i++) {
- buffer = exynos_drm_fb_buffer(fb, i);
- if (!buffer) {
- DRM_LOG_KMS("buffer is null\n");
- return -EFAULT;
- }
-
- overlay->dma_addr[i] = buffer->dma_addr;
- overlay->vaddr[i] = buffer->kvaddr;
-
- DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n",
- i, (unsigned long)overlay->vaddr[i],
- (unsigned long)overlay->dma_addr[i]);
- }
-
- actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
- actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
-
- /* set drm framebuffer data. */
- overlay->fb_x = pos->fb_x;
- overlay->fb_y = pos->fb_y;
- overlay->fb_width = fb->width;
- overlay->fb_height = fb->height;
- overlay->src_width = pos->src_w;
- overlay->src_height = pos->src_h;
- overlay->bpp = fb->bits_per_pixel;
- overlay->pitch = fb->pitches[0];
- overlay->pixel_format = fb->pixel_format;
-
- /* set overlay range to be displayed. */
- overlay->crtc_x = pos->crtc_x;
- overlay->crtc_y = pos->crtc_y;
- overlay->crtc_width = actual_w;
- overlay->crtc_height = actual_h;
-
- /* set drm mode data. */
- overlay->mode_width = mode->hdisplay;
- overlay->mode_height = mode->vdisplay;
- overlay->refresh = mode->vrefresh;
- overlay->scan_flag = mode->flags;
-
- DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
- overlay->crtc_x, overlay->crtc_y,
- overlay->crtc_width, overlay->crtc_height);
-
- return 0;
-}
-
-static int exynos_drm_crtc_update(struct drm_crtc *crtc)
-{
- struct exynos_drm_crtc *exynos_crtc;
- struct exynos_drm_overlay *overlay;
- struct exynos_drm_crtc_pos pos;
- struct drm_display_mode *mode = &crtc->mode;
- struct drm_framebuffer *fb = crtc->fb;
-
- if (!mode || !fb)
- return -EINVAL;
-
- exynos_crtc = to_exynos_crtc(crtc);
- overlay = &exynos_crtc->overlay;
-
- memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos));
-
- /* it means the offset of framebuffer to be displayed. */
- pos.fb_x = crtc->x;
- pos.fb_y = crtc->y;
-
- /* OSD position to be displayed. */
- pos.crtc_x = 0;
- pos.crtc_y = 0;
- pos.crtc_w = fb->width - crtc->x;
- pos.crtc_h = fb->height - crtc->y;
- pos.src_w = pos.crtc_w;
- pos.src_h = pos.crtc_h;
-
- return exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos);
-}
-
static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct drm_device *dev = crtc->dev;
@@ -175,23 +78,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
mutex_lock(&dev->struct_mutex);
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- exynos_drm_fn_encoder(crtc, &mode,
- exynos_drm_encoder_crtc_dpms);
- exynos_crtc->dpms = mode;
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- exynos_drm_fn_encoder(crtc, &mode,
- exynos_drm_encoder_crtc_dpms);
- exynos_crtc->dpms = mode;
- break;
- default:
- DRM_ERROR("unspecified mode %d\n", mode);
- break;
- }
+ exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms);
+ exynos_crtc->dpms = mode;
mutex_unlock(&dev->struct_mutex);
}
@@ -209,30 +97,8 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
DRM_DEBUG_KMS("%s\n", __FILE__);
- /*
- * when set_crtc is requested from user or at booting time,
- * crtc->commit would be called without dpms call so if dpms is
- * no power on then crtc->dpms should be called
- * with DRM_MODE_DPMS_ON for the hardware power to be on.
- */
- if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) {
- int mode = DRM_MODE_DPMS_ON;
-
- /*
- * enable hardware(power on) to all encoders hdmi connected
- * to current crtc.
- */
- exynos_drm_crtc_dpms(crtc, mode);
- /*
- * enable dma to all encoders connected to current crtc and
- * lcd panel.
- */
- exynos_drm_fn_encoder(crtc, &mode,
- exynos_drm_encoder_dpms_from_crtc);
- }
-
- exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
- exynos_drm_encoder_crtc_commit);
+ exynos_plane_commit(exynos_crtc->plane);
+ exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON);
}
static bool
@@ -251,31 +117,61 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb)
{
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+ struct drm_plane *plane = exynos_crtc->plane;
+ unsigned int crtc_w;
+ unsigned int crtc_h;
+ int pipe = exynos_crtc->pipe;
+ int ret;
+
DRM_DEBUG_KMS("%s\n", __FILE__);
+ exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+
/*
* copy the mode data adjusted by mode_fixup() into crtc->mode
* so that hardware can be seet to proper mode.
*/
memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
- return exynos_drm_crtc_update(crtc);
+ crtc_w = crtc->fb->width - x;
+ crtc_h = crtc->fb->height - y;
+
+ ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h,
+ x, y, crtc_w, crtc_h);
+ if (ret)
+ return ret;
+
+ plane->crtc = crtc;
+ plane->fb = crtc->fb;
+
+ exynos_drm_fn_encoder(crtc, &pipe, exynos_drm_encoder_crtc_pipe);
+
+ return 0;
}
static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
{
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+ struct drm_plane *plane = exynos_crtc->plane;
+ unsigned int crtc_w;
+ unsigned int crtc_h;
int ret;
DRM_DEBUG_KMS("%s\n", __FILE__);
- ret = exynos_drm_crtc_update(crtc);
+ crtc_w = crtc->fb->width - x;
+ crtc_h = crtc->fb->height - y;
+
+ ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h,
+ x, y, crtc_w, crtc_h);
if (ret)
return ret;
- exynos_drm_crtc_apply(crtc);
+ exynos_drm_crtc_commit(crtc);
- return ret;
+ return 0;
}
static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc)
@@ -284,6 +180,16 @@ static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc)
/* drm framework doesn't check NULL */
}
+static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
+{
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_OFF);
+ exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
.dpms = exynos_drm_crtc_dpms,
.prepare = exynos_drm_crtc_prepare,
@@ -292,6 +198,7 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
.mode_set = exynos_drm_crtc_mode_set,
.mode_set_base = exynos_drm_crtc_mode_set_base,
.load_lut = exynos_drm_crtc_load_lut,
+ .disable = exynos_drm_crtc_disable,
};
static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
@@ -327,7 +234,8 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
&dev_priv->pageflip_event_list);
crtc->fb = fb;
- ret = exynos_drm_crtc_update(crtc);
+ ret = exynos_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y,
+ NULL);
if (ret) {
crtc->fb = old_fb;
drm_vblank_put(dev, exynos_crtc->pipe);
@@ -335,14 +243,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
goto out;
}
-
- /*
- * the values related to a buffer of the drm framebuffer
- * to be applied should be set at here. because these values
- * first, are set to shadow registers and then to
- * real registers at vsync front porch period.
- */
- exynos_drm_crtc_apply(crtc);
}
out:
mutex_unlock(&dev->struct_mutex);
@@ -362,18 +262,73 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
kfree(exynos_crtc);
}
+static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,
+ struct drm_property *property,
+ uint64_t val)
+{
+ struct drm_device *dev = crtc->dev;
+ struct exynos_drm_private *dev_priv = dev->dev_private;
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ if (property == dev_priv->crtc_mode_property) {
+ enum exynos_crtc_mode mode = val;
+
+ if (mode == exynos_crtc->mode)
+ return 0;
+
+ exynos_crtc->mode = mode;
+
+ switch (mode) {
+ case CRTC_MODE_NORMAL:
+ exynos_drm_crtc_commit(crtc);
+ break;
+ case CRTC_MODE_BLANK:
+ exynos_plane_dpms(exynos_crtc->plane,
+ DRM_MODE_DPMS_OFF);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static struct drm_crtc_funcs exynos_crtc_funcs = {
.set_config = drm_crtc_helper_set_config,
.page_flip = exynos_drm_crtc_page_flip,
.destroy = exynos_drm_crtc_destroy,
+ .set_property = exynos_drm_crtc_set_property,
+};
+
+static const struct drm_prop_enum_list mode_names[] = {
+ { CRTC_MODE_NORMAL, "normal" },
+ { CRTC_MODE_BLANK, "blank" },
};
-struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev,
- struct drm_crtc *crtc)
+static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
{
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct exynos_drm_private *dev_priv = dev->dev_private;
+ struct drm_property *prop;
- return &exynos_crtc->overlay;
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ prop = dev_priv->crtc_mode_property;
+ if (!prop) {
+ prop = drm_property_create_enum(dev, 0, "mode", mode_names,
+ ARRAY_SIZE(mode_names));
+ if (!prop)
+ return;
+
+ dev_priv->crtc_mode_property = prop;
+ }
+
+ drm_object_attach_property(&crtc->base, prop, 0);
}
int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
@@ -391,8 +346,13 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
}
exynos_crtc->pipe = nr;
- exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
- exynos_crtc->overlay.zpos = DEFAULT_ZPOS;
+ exynos_crtc->dpms = DRM_MODE_DPMS_ON;
+ exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true);
+ if (!exynos_crtc->plane) {
+ kfree(exynos_crtc);
+ return -ENOMEM;
+ }
+
crtc = &exynos_crtc->drm_crtc;
private->crtc[nr] = crtc;
@@ -400,6 +360,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
drm_crtc_init(dev, crtc, &exynos_crtc_funcs);
drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
+ exynos_drm_crtc_attach_mode_property(crtc);
+
return 0;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 16b8e21..6bae8d8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -29,39 +29,8 @@
#ifndef _EXYNOS_DRM_CRTC_H_
#define _EXYNOS_DRM_CRTC_H_
-struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev,
- struct drm_crtc *crtc);
int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
-/*
- * Exynos specific crtc postion structure.
- *
- * @fb_x: offset x on a framebuffer to be displyed
- * - the unit is screen coordinates.
- * @fb_y: offset y on a framebuffer to be displayed
- * - the unit is screen coordinates.
- * @src_w: width of source area to be displayed from a framebuffer.
- * @src_h: height of source area to be displayed from a framebuffer.
- * @crtc_x: offset x on hardware screen.
- * @crtc_y: offset y on hardware screen.
- * @crtc_w: width of hardware screen.
- * @crtc_h: height of hardware screen.
- */
-struct exynos_drm_crtc_pos {
- unsigned int fb_x;
- unsigned int fb_y;
- unsigned int src_w;
- unsigned int src_h;
- unsigned int crtc_x;
- unsigned int crtc_y;
- unsigned int crtc_w;
- unsigned int crtc_h;
-};
-
-int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
- struct drm_framebuffer *fb,
- struct drm_display_mode *mode,
- struct exynos_drm_crtc_pos *pos);
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
index ca40c68..128627c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
@@ -25,6 +25,7 @@
#include "drmP.h"
#include "drm.h"
+#include "exynos_drm.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_gem.h"
@@ -235,6 +236,9 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
if (sgt->nents == 1) {
buffer->dma_addr = sg_dma_address(sgt->sgl);
buffer->size = sg_dma_len(sgt->sgl);
+
+ /* always physically continuous memory if sgt->nents is 1. */
+ exynos_gem_obj->flags |= EXYNOS_BO_CONTIG;
} else {
unsigned int i = 0;
@@ -245,28 +249,24 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
sgl = sg_next(sgl);
i++;
}
+
+ /*
+ * this case could be CONTIG or NONCONTIG type but now CONTIG.
+ * we have to find a way that exporter can notify the type of
+ * its own buffer to importer. TODO
+ */
+ exynos_gem_obj->flags |= EXYNOS_BO_NONCONTIG;
}
exynos_gem_obj->buffer = buffer;
buffer->sgt = sgt;
exynos_gem_obj->base.import_attach = attach;
- /* register buffer information to private buffer manager. */
- ret = register_buf_to_priv_mgr(exynos_gem_obj,
- &exynos_gem_obj->priv_handle,
- &exynos_gem_obj->priv_id);
- if (ret < 0)
- goto err_release_gem;
-
- DRM_DEBUG_PRIME("ump id = %d, dma_addr = 0x%x, size = 0x%lx\n",
- exynos_gem_obj->priv_id, buffer->dma_addr, buffer->size);
+ DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n", buffer->dma_addr,
+ buffer->size);
return &exynos_gem_obj->base;
-err_release_gem:
- drm_gem_object_release(&exynos_gem_obj->base);
- kfree(exynos_gem_obj);
- exynos_gem_obj = NULL;
err_free_pages:
kfree(buffer->pages);
buffer->pages = NULL;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 340a8d6..90cff3f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -38,12 +38,13 @@
#include "exynos_drm_fb.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_g2d.h"
-#include "exynos_drm_rotator.h"
+#include "exynos_drm_ipp.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_vidi.h"
#include "exynos_drm_dmabuf.h"
+#include "exynos_drm_iommu.h"
-#define DRIVER_NAME "exynos-drm"
+#define DRIVER_NAME "exynos"
#define DRIVER_DESC "Samsung SoC DRM"
#define DRIVER_DATE "20110530"
#define DRIVER_MAJOR 1
@@ -51,53 +52,65 @@
#define VBLANK_OFF_DELAY 50000
-static int exynos_drm_list_gem_info(int id, void *ptr, void *data)
+struct exynos_drm_gem_info_data {
+ struct drm_file *filp;
+ struct seq_file *m;
+};
+
+static int exynos_drm_gem_one_info(int id, void *ptr, void *data)
{
struct drm_gem_object *obj = ptr;
- struct drm_file *filp = data;
- struct exynos_drm_gem_obj *gem = to_exynos_gem_obj(obj);
- struct exynos_drm_gem_buf *buf = gem->buffer;
-
- DRM_INFO("%3d \t%3d \t%2d \t\t%2d \t0x%lx \t0x%x \t0x%lx "\
- "\t%2d \t\t%2d \t\t%2d\n",
- filp->pid,
- id,
- atomic_read(&obj->refcount.refcount),
- atomic_read(&obj->handle_count),
- gem->size,
- gem->flags,
- buf->page_size,
- buf->pfnmap,
- obj->export_dma_buf ? 1 : 0,
- obj->import_attach ? 1 : 0);
+ struct exynos_drm_gem_info_data *gem_info_data = data;
+ struct drm_exynos_file_private *file_priv =
+ gem_info_data->filp->driver_priv;
+ struct exynos_drm_gem_obj *exynos_gem = to_exynos_gem_obj(obj);
+ struct exynos_drm_gem_buf *buf = exynos_gem->buffer;
+
+ seq_printf(gem_info_data->m, "%3d \t%3d \t%3d \t%2d \t\t%2d \t0x%08lx"\
+ " \t0x%x \t0x%08lx \t%2d \t\t%2d \t\t%2d\n",
+ gem_info_data->filp->pid,
+ file_priv->tgid,
+ id,
+ atomic_read(&obj->refcount.refcount),
+ atomic_read(&obj->handle_count),
+ exynos_gem->size,
+ exynos_gem->flags,
+ buf->page_size,
+ buf->pfnmap,
+ obj->export_dma_buf ? 1 : 0,
+ obj->import_attach ? 1 : 0);
return 0;
}
-static ssize_t exynos_drm_show_gem_info(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int exynos_drm_gem_info(struct seq_file *m, void *data)
{
- struct drm_device *drm_dev = dev_get_drvdata(dev);
- struct drm_file *filp;
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *drm_dev = node->minor->dev;
+ struct exynos_drm_gem_info_data gem_info_data;
+
+ gem_info_data.m = m;
- DRM_INFO("pid \thandle \trefcount \thcount \tsize \t\tflags "\
- "\tpage_size \tpfnmap \texport_to_fd \timport_from_fd\n");
+ seq_printf(gem_info_data.m, "pid \ttgid \thandle \trefcount \thcount "\
+ "\tsize \t\tflags \tpage_size \tpfnmap \t"\
+ "exyport_to_fd \timport_from_fd\n");
- list_for_each_entry(filp, &drm_dev->filelist, lhead)
- idr_for_each(&filp->object_idr, &exynos_drm_list_gem_info,
- filp);
+ list_for_each_entry(gem_info_data.filp, &drm_dev->filelist, lhead)
+ idr_for_each(&gem_info_data.filp->object_idr,
+ exynos_drm_gem_one_info, &gem_info_data);
- return strlen(buf);
+ return 0;
}
-static const struct device_attribute exynos_device_attrs[] = {
- __ATTR(gem_info, S_IRUGO, exynos_drm_show_gem_info, NULL)
+static struct drm_info_list exynos_drm_debugfs_list[] = {
+ {"gem_info", exynos_drm_gem_info, DRIVER_GEM},
};
+#define EXYNOS_DRM_DEBUGFS_ENTRIES ARRAY_SIZE(exynos_drm_debugfs_list)
static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
{
struct exynos_drm_private *private;
+ struct drm_minor *minor;
int ret;
int nr;
@@ -109,6 +122,17 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
return -ENOMEM;
}
+ /* maximum size of userptr is limited to 16MB as default. */
+ private->userptr_limit = SZ_16M;
+
+ /* setup device address space for iommu. */
+ private->vmm = exynos_drm_iommu_setup(0x80000000, 0x40000000);
+ if (IS_ERR(private->vmm)) {
+ DRM_ERROR("failed to setup iommu.\n");
+ kfree(private);
+ return PTR_ERR(private->vmm);
+ }
+
INIT_LIST_HEAD(&private->pageflip_event_list);
dev->dev_private = (void *)private;
@@ -130,8 +154,11 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
}
for (nr = 0; nr < MAX_PLANE; nr++) {
- ret = exynos_plane_init(dev, nr);
- if (ret)
+ struct drm_plane *plane;
+ unsigned int possible_crtcs = (1 << MAX_CRTC) - 1;
+
+ plane = exynos_plane_init(dev, possible_crtcs, false);
+ if (!plane)
goto err_crtc;
}
@@ -163,9 +190,12 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
drm_vblank_offdelay = VBLANK_OFF_DELAY;
- ret = device_create_file(dev->dev, &exynos_device_attrs[0]);
- if (ret < 0)
- DRM_DEBUG_DRIVER("failed to create sysfs.\n");
+ minor = dev->primary;
+ ret = drm_debugfs_create_files(exynos_drm_debugfs_list,
+ EXYNOS_DRM_DEBUGFS_ENTRIES,
+ minor->debugfs_root, minor);
+ if (ret)
+ DRM_DEBUG_DRIVER("failed to create exynos-drm debugfs.\n");
return 0;
@@ -182,8 +212,15 @@ err_crtc:
static int exynos_drm_unload(struct drm_device *dev)
{
+ struct exynos_drm_private *private;
+
+ private = dev->dev_private;
+
DRM_DEBUG_DRIVER("%s\n", __FILE__);
+ /* release vmm object and device address space for iommu. */
+ exynos_drm_iommu_cleanup(private->vmm);
+
exynos_drm_fbdev_fini(dev);
exynos_drm_device_unregister(dev);
drm_vblank_cleanup(dev);
@@ -193,6 +230,9 @@ static int exynos_drm_unload(struct drm_device *dev)
dev->dev_private = NULL;
+ drm_debugfs_remove_files(exynos_drm_debugfs_list,
+ EXYNOS_DRM_DEBUGFS_ENTRIES, dev->primary);
+
return 0;
}
@@ -206,6 +246,8 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
if (!file_priv)
return -ENOMEM;
+ file_priv->tgid = task_tgid_nr(current);
+
drm_prime_init_file_private(&file->prime);
file->driver_priv = file_priv;
@@ -271,6 +313,9 @@ static struct drm_ioctl_desc exynos_ioctls[] = {
exynos_drm_gem_userptr_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET,
exynos_drm_gem_get_ioctl, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(EXYNOS_USER_LIMIT,
+ exynos_drm_gem_user_limit_ioctl, DRM_MASTER |
+ DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_EXPORT_UMP,
exynos_drm_gem_export_ump_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CACHE_OP,
@@ -280,8 +325,6 @@ static struct drm_ioctl_desc exynos_ioctls[] = {
exynos_drm_gem_get_phy_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_PHY_IMP,
exynos_drm_gem_phy_imp_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS,
- exynos_plane_set_zpos_ioctl, DRM_UNLOCKED | DRM_AUTH),
DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION,
vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH),
@@ -292,8 +335,14 @@ static struct drm_ioctl_desc exynos_ioctls[] = {
DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC,
exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH),
- DRM_IOCTL_DEF_DRV(EXYNOS_ROTATOR_EXEC,
- exynos_drm_rotator_exec_ioctl, DRM_UNLOCKED | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY,
+ exynos_drm_ipp_get_property, DRM_UNLOCKED | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY,
+ exynos_drm_ipp_set_property, DRM_UNLOCKED | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(EXYNOS_IPP_BUF,
+ exynos_drm_ipp_buf, DRM_UNLOCKED | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CTRL,
+ exynos_drm_ipp_ctrl, DRM_UNLOCKED | DRM_AUTH),
};
static const struct file_operations exynos_drm_driver_fops = {
@@ -307,8 +356,8 @@ static const struct file_operations exynos_drm_driver_fops = {
};
static struct drm_driver exynos_drm_driver = {
- .driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM |
- DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
+ .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET |
+ DRIVER_GEM | DRIVER_PRIME,
.load = exynos_drm_load,
.unload = exynos_drm_unload,
.open = exynos_drm_open,
@@ -407,6 +456,24 @@ static int __init exynos_drm_init(void)
goto out_rotator;
#endif
+#ifdef CONFIG_DRM_EXYNOS_FIMC
+ ret = platform_driver_register(&fimc_driver);
+ if (ret < 0)
+ goto out_fimc;
+#endif
+
+#ifdef CONFIG_DRM_EXYNOS_GSC
+ ret = platform_driver_register(&gsc_driver);
+ if (ret < 0)
+ goto out_gsc;
+#endif
+
+#ifdef CONFIG_DRM_EXYNOS_IPP
+ ret = platform_driver_register(&ipp_driver);
+ if (ret < 0)
+ goto out_ipp;
+#endif
+
ret = platform_driver_register(&exynos_drm_platform_driver);
if (ret < 0)
goto out;
@@ -414,6 +481,21 @@ static int __init exynos_drm_init(void)
return 0;
out:
+#ifdef CONFIG_DRM_EXYNOS_IPP
+ platform_driver_unregister(&ipp_driver);
+out_ipp:
+#endif
+
+#ifdef CONFIG_DRM_EXYNOS_GSC
+ platform_driver_unregister(&gsc_driver);
+out_gsc:
+#endif
+
+#ifdef CONFIG_DRM_EXYNOS_FIMC
+ platform_driver_unregister(&fimc_driver);
+out_fimc:
+#endif
+
#ifdef CONFIG_DRM_EXYNOS_ROTATOR
platform_driver_unregister(&rotator_driver);
out_rotator:
@@ -451,6 +533,18 @@ static void __exit exynos_drm_exit(void)
platform_driver_unregister(&exynos_drm_platform_driver);
+#ifdef CONFIG_DRM_EXYNOS_IPP
+ platform_driver_unregister(&ipp_driver);
+#endif
+
+#ifdef CONFIG_DRM_EXYNOS_GSC
+ platform_driver_unregister(&gsc_driver);
+#endif
+
+#ifdef CONFIG_DRM_EXYNOS_FIMC
+ platform_driver_unregister(&fimc_driver);
+#endif
+
#ifdef CONFIG_DRM_EXYNOS_ROTATOR
platform_driver_unregister(&rotator_driver);
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 463b086..8cdf93b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -59,12 +59,14 @@ enum exynos_drm_output_type {
*
* @mode_set: copy drm overlay info to hw specific overlay info.
* @commit: apply hardware specific overlay data to registers.
+ * @enable: enable hardware specific overlay.
* @disable: disable hardware specific overlay.
*/
struct exynos_drm_overlay_ops {
void (*mode_set)(struct device *subdrv_dev,
struct exynos_drm_overlay *overlay);
void (*commit)(struct device *subdrv_dev, int zpos);
+ void (*enable)(struct device *subdrv_dev, int zpos);
void (*disable)(struct device *subdrv_dev, int zpos);
};
@@ -220,32 +222,30 @@ struct iommu_info_node {
* Exynos drm g2d private structure
*
* @dev: device object to device driver for using iommu.
- * @iommu_map_list: list head to iommu map information.
- * each device driver using iommu should have its own iommu_map_list
- * because device drivers have their own device address space and
- * the device address spaces could be duplicated echo other.
*/
struct exynos_drm_g2d_private {
struct device *dev;
struct list_head inuse_cmdlist;
struct list_head event_list;
- struct list_head iommu_map_list;
};
/*
- * Exynos drm rotator private structure
+ * Exynos drm ipp private structure
*
* @dev: device object to device driver for using driver data.
- * @iommu_list: list head to iommu map information.
+ * @ippdrv: link used ippdrv.
+ * @event_list: list head to event.
*/
-struct exynos_drm_rot_private {
- struct device *dev;
- struct list_head iommu_list;
+struct exynos_drm_ipp_private {
+ struct device *dev;
+ void *ippdrv;
+ struct list_head event_list;
};
struct drm_exynos_file_private {
struct exynos_drm_g2d_private *g2d_priv;
- struct exynos_drm_rot_private *rot_priv;
+ struct exynos_drm_ipp_private *ipp_priv;
+ pid_t tgid;
};
/*
@@ -262,6 +262,18 @@ struct exynos_drm_private {
* this array is used to be aware of which crtc did it request vblank.
*/
struct drm_crtc *crtc[MAX_CRTC];
+
+ /*
+ * maximum size of allocation by userptr feature.
+ * - as default, this has 16MB and only root user can change it.
+ */
+ unsigned long userptr_limit;
+
+ /* a iovmm object for iommu support. */
+ void *vmm;
+
+ struct drm_property *plane_zpos_property;
+ struct drm_property *crtc_mode_property;
};
/*
@@ -289,7 +301,7 @@ struct exynos_drm_subdrv {
struct exynos_drm_manager *manager;
int (*probe)(struct drm_device *drm_dev, struct device *dev);
- void (*remove)(struct drm_device *dev);
+ void (*remove)(struct drm_device *drm_dev, struct device *dev);
int (*open)(struct drm_device *drm_dev, struct device *dev,
struct drm_file *file);
void (*close)(struct drm_device *drm_dev, struct device *dev,
@@ -332,4 +344,7 @@ extern struct platform_driver exynos_drm_common_hdmi_driver;
extern struct platform_driver vidi_driver;
extern struct platform_driver g2d_driver;
extern struct platform_driver rotator_driver;
+extern struct platform_driver fimc_driver;
+extern struct platform_driver gsc_driver;
+extern struct platform_driver ipp_driver;
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index 6e9ac7b..ebc4456 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -30,7 +30,6 @@
#include "drm_crtc_helper.h"
#include "exynos_drm_drv.h"
-#include "exynos_drm_crtc.h"
#include "exynos_drm_encoder.h"
#define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder,\
@@ -136,21 +135,16 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
struct drm_connector *connector;
struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
struct exynos_drm_manager_ops *manager_ops = manager->ops;
- struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- struct exynos_drm_overlay *overlay = get_exynos_drm_overlay(dev,
- encoder->crtc);
DRM_DEBUG_KMS("%s\n", __FILE__);
+ exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder) {
+ if (connector->encoder == encoder)
if (manager_ops && manager_ops->mode_set)
manager_ops->mode_set(manager->dev,
adjusted_mode);
-
- if (overlay_ops && overlay_ops->mode_set)
- overlay_ops->mode_set(manager->dev, overlay);
- }
}
}
@@ -261,7 +255,7 @@ exynos_drm_encoder_create(struct drm_device *dev,
return NULL;
}
- exynos_encoder->dpms = DRM_MODE_DPMS_OFF;
+ exynos_encoder->dpms = DRM_MODE_DPMS_ON;
exynos_encoder->manager = manager;
encoder = &exynos_encoder->drm_encoder;
encoder->possible_crtcs = possible_crtcs;
@@ -317,8 +311,8 @@ void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
struct exynos_drm_manager_ops *manager_ops = manager->ops;
int crtc = *(int *)data;
- if (manager->pipe == -1)
- manager->pipe = crtc;
+ if (manager->pipe != crtc)
+ return;
if (manager_ops->enable_vblank)
manager_ops->enable_vblank(manager->dev);
@@ -331,34 +325,41 @@ void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
struct exynos_drm_manager_ops *manager_ops = manager->ops;
int crtc = *(int *)data;
- if (manager->pipe == -1)
- manager->pipe = crtc;
+ if (manager->pipe != crtc)
+ return;
if (manager_ops->disable_vblank)
manager_ops->disable_vblank(manager->dev);
}
-void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder,
- void *data)
+void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
{
- struct exynos_drm_manager *manager =
- to_exynos_encoder(encoder)->manager;
- struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- int zpos = DEFAULT_ZPOS;
+ struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+ struct exynos_drm_manager *manager = exynos_encoder->manager;
+ struct exynos_drm_manager_ops *manager_ops = manager->ops;
+ int mode = *(int *)data;
- if (data)
- zpos = *(int *)data;
+ DRM_DEBUG_KMS("%s\n", __FILE__);
- if (overlay_ops && overlay_ops->commit)
- overlay_ops->commit(manager->dev, zpos);
+ if (manager_ops && manager_ops->dpms)
+ manager_ops->dpms(manager->dev, mode);
+
+ /*
+ * if this condition is ok then it means that the crtc is already
+ * detached from encoder and last function for detaching is properly
+ * done, so clear pipe from manager to prevent repeated call.
+ */
+ if (mode > DRM_MODE_DPMS_ON) {
+ if (!encoder->crtc)
+ manager->pipe = -1;
+ }
}
-void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data)
+void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data)
{
struct exynos_drm_manager *manager =
to_exynos_encoder(encoder)->manager;
- int crtc = *(int *)data;
- int zpos = DEFAULT_ZPOS;
+ int pipe = *(int *)data;
DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -366,76 +367,62 @@ void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data)
* when crtc is detached from encoder, this pipe is used
* to select manager operation
*/
- manager->pipe = crtc;
-
- exynos_drm_encoder_crtc_plane_commit(encoder, &zpos);
+ manager->pipe = pipe;
}
-void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, void *data)
+void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
{
- struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
- int mode = *(int *)data;
+ struct exynos_drm_manager *manager =
+ to_exynos_encoder(encoder)->manager;
+ struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+ struct exynos_drm_overlay *overlay = data;
DRM_DEBUG_KMS("%s\n", __FILE__);
- exynos_drm_encoder_dpms(encoder, mode);
-
- exynos_encoder->dpms = mode;
+ if (overlay_ops && overlay_ops->mode_set)
+ overlay_ops->mode_set(manager->dev, overlay);
}
-void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
+void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
{
- struct drm_device *dev = encoder->dev;
- struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
- struct exynos_drm_manager *manager = exynos_encoder->manager;
- struct exynos_drm_manager_ops *manager_ops = manager->ops;
- struct drm_connector *connector;
- int mode = *(int *)data;
+ struct exynos_drm_manager *manager =
+ to_exynos_encoder(encoder)->manager;
+ struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+ int zpos = DEFAULT_ZPOS;
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (manager_ops && manager_ops->dpms)
- manager_ops->dpms(manager->dev, mode);
-
- /*
- * set current dpms mode to the connector connected to
- * current encoder. connector->dpms would be checked
- * at drm_helper_connector_dpms()
- */
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- if (connector->encoder == encoder)
- connector->dpms = mode;
+ if (data)
+ zpos = *(int *)data;
- /*
- * if this condition is ok then it means that the crtc is already
- * detached from encoder and last function for detaching is properly
- * done, so clear pipe from manager to prevent repeated call.
- */
- if (mode > DRM_MODE_DPMS_ON) {
- if (!encoder->crtc)
- manager->pipe = -1;
- }
+ if (overlay_ops && overlay_ops->commit)
+ overlay_ops->commit(manager->dev, zpos);
}
-void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
+void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
{
struct exynos_drm_manager *manager =
to_exynos_encoder(encoder)->manager;
struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- struct exynos_drm_overlay *overlay = data;
+ int zpos = DEFAULT_ZPOS;
- if (overlay_ops && overlay_ops->mode_set)
- overlay_ops->mode_set(manager->dev, overlay);
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (data)
+ zpos = *(int *)data;
+
+ if (overlay_ops && overlay_ops->enable)
+ overlay_ops->enable(manager->dev, zpos);
}
-void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data)
+void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
{
struct exynos_drm_manager *manager =
to_exynos_encoder(encoder)->manager;
struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
int zpos = DEFAULT_ZPOS;
- DRM_DEBUG_KMS("\n");
+ DRM_DEBUG_KMS("%s\n", __FILE__);
if (data)
zpos = *(int *)data;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h
index eb7d231..6470d9d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h
@@ -40,13 +40,11 @@ void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
void (*fn)(struct drm_encoder *, void *));
void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data);
void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder,
- void *data);
-void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder,
- void *data);
void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data);
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 7b47330..41009e4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -49,10 +49,19 @@ struct exynos_drm_fb {
struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER];
};
-static int check_fb_gem_memory_type(struct exynos_drm_gem_obj *exynos_gem_obj)
+static int check_fb_gem_memory_type(struct drm_device *drm_dev,
+ struct exynos_drm_gem_obj *exynos_gem_obj)
{
+ struct exynos_drm_private *private = drm_dev->dev_private;
unsigned int flags;
+ /*
+ * if exynos drm driver supports iommu then framebuffer can use
+ * all the buffer types.
+ */
+ if (private->vmm)
+ return 0;
+
flags = exynos_gem_obj->flags;
/* not support physically non-continuous memory for fb yet. TODO */
@@ -64,14 +73,63 @@ static int check_fb_gem_memory_type(struct exynos_drm_gem_obj *exynos_gem_obj)
return 0;
}
+static int check_fb_gem_size(struct drm_device *drm_dev,
+ struct drm_framebuffer *fb,
+ unsigned int nr)
+{
+ unsigned long fb_size;
+ struct drm_gem_object *obj;
+ struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+
+ /* in case of RGB format, only one plane is used. */
+ if (nr < 2) {
+ exynos_gem_obj = exynos_fb->exynos_gem_obj[0];
+ obj = &exynos_gem_obj->base;
+ fb_size = fb->pitches[0] * fb->height;
+
+ if (fb_size != exynos_gem_obj->packed_size) {
+ DRM_ERROR("invalid fb or gem size.\n");
+ return -EINVAL;
+ }
+ /* in case of NV12MT, YUV420M and so on, two and three planes. */
+ } else {
+ unsigned int i;
+
+ for (i = 0; i < nr; i++) {
+ exynos_gem_obj = exynos_fb->exynos_gem_obj[i];
+ obj = &exynos_gem_obj->base;
+ fb_size = fb->pitches[i] * fb->height;
+
+ if (fb_size != exynos_gem_obj->packed_size) {
+ DRM_ERROR("invalid fb or gem size.\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
{
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+ unsigned int i;
DRM_DEBUG_KMS("%s\n", __FILE__);
drm_framebuffer_cleanup(fb);
+ for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem_obj); i++) {
+ struct drm_gem_object *obj;
+
+ if (exynos_fb->exynos_gem_obj[i] == NULL)
+ continue;
+
+ obj = &exynos_fb->exynos_gem_obj[i]->base;
+ drm_gem_object_unreference_unlocked(obj);
+ }
+
kfree(exynos_fb);
exynos_fb = NULL;
}
@@ -117,7 +175,7 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
exynos_gem_obj = to_exynos_gem_obj(obj);
- ret = check_fb_gem_memory_type(exynos_gem_obj);
+ ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
if (ret < 0) {
DRM_ERROR("cannot use this gem memory type for fb.\n");
return ERR_PTR(-EINVAL);
@@ -149,8 +207,7 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
struct drm_gem_object *obj;
struct drm_framebuffer *fb;
struct exynos_drm_fb *exynos_fb;
- int nr;
- int i;
+ int nr, i, ret;
DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -160,11 +217,11 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
return ERR_PTR(-ENOENT);
}
- drm_gem_object_unreference_unlocked(obj);
-
fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj);
- if (IS_ERR(fb))
+ if (IS_ERR(fb)) {
+ drm_gem_object_unreference_unlocked(obj);
return fb;
+ }
exynos_fb = to_exynos_fb(fb);
nr = exynos_drm_format_num_buffers(fb->pixel_format);
@@ -181,11 +238,9 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
return ERR_PTR(-ENOENT);
}
- drm_gem_object_unreference_unlocked(obj);
-
exynos_gem_obj = to_exynos_gem_obj(obj);
- ret = check_fb_gem_memory_type(exynos_gem_obj);
+ ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
if (ret < 0) {
DRM_ERROR("cannot use this gem memory type for fb.\n");
exynos_drm_fb_destroy(fb);
@@ -195,6 +250,12 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj);
}
+ ret = check_fb_gem_size(dev, fb, nr);
+ if (ret < 0) {
+ exynos_drm_fb_destroy(fb);
+ return ERR_PTR(ret);
+ }
+
return fb;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index d5586cc..df34adf 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -82,9 +82,9 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
offset += fbi->var.yoffset * fb->pitches[0];
- dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr;
+ dev->mode_config.fb_base = (resource_size_t)buffer->paddr;
fbi->screen_base = buffer->kvaddr + offset;
- fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset);
+ fbi->fix.smem_start = (unsigned long)(buffer->paddr + offset);
fbi->screen_size = size;
fbi->fix.smem_len = size;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
new file mode 100644
index 0000000..fdf5be8
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -0,0 +1,1925 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co.Ltd
+ * Authors:
+ * Eunchul Kim <chulspro.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include "drmP.h"
+#include "drm_backlight.h"
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/cma.h>
+#include <plat/map-base.h>
+
+#include "regs-fimc.h"
+#include <drm/exynos_drm.h>
+#include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_ipp.h"
+#include "exynos_drm_fimc.h"
+
+/*
+ * FIMC is stand for Fully Interactive Mobile Camera and
+ * supports image scaler/rotator and input/output DMA operations.
+ * input DMA reads image data from the memory.
+ * output DMA writes image data to memory.
+ * FIMC supports image rotation and image effect functions.
+ */
+
+#define FIMC_MAX_DEVS 4
+#define FIMC_MAX_SRC 2
+#define FIMC_MAX_DST 32
+#ifdef CONFIG_SLP_DISP_DEBUG
+#define FIMC_MAX_REG 128
+#define FIMC_BASE_REG(id) (0x11800000 + (0x10000 * id))
+#endif
+#define FIMC_CLK_RATE 166750000
+#define FIMC_BUF_STOP 1
+#define FIMC_BUF_START 2
+#define FIMC_REG_SZ 32
+#define FIMC_WIDTH_ITU_709 1280
+
+#define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
+#define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
+ struct fimc_context, ippdrv);
+#define fimc_read(offset) readl(ctx->regs + (offset));
+#define fimc_write(cfg, offset) writel(cfg, ctx->regs + (offset));
+
+enum fimc_wb {
+ FIMC_WB_NONE,
+ FIMC_WB_A,
+ FIMC_WB_B,
+};
+
+/*
+ * A structure of scaler.
+ *
+ * @range: narrow, wide.
+ * @bypass: unused scaler path.
+ * @up_h: horizontal scale up.
+ * @up_v: vertical scale up.
+ * @hratio: horizontal ratio.
+ * @vratio: vertical ratio.
+ */
+struct fimc_scaler {
+ bool range;
+ bool bypass;
+ bool up_h;
+ bool up_v;
+ u32 hratio;
+ u32 vratio;
+};
+
+/*
+ * A structure of scaler capability.
+ *
+ * find user manual table 43-1.
+ * @in_hori: scaler input horizontal size.
+ * @bypass: scaler bypass mode.
+ * @dst_h_wo_rot: target horizontal size without output rotation.
+ * @dst_h_rot: target horizontal size with output rotation.
+ * @rl_w_wo_rot: real width without input rotation.
+ * @rl_h_rot: real height without output rotation.
+ */
+struct fimc_capability {
+ /* scaler */
+ u32 in_hori;
+ u32 bypass;
+ /* output rotator */
+ u32 dst_h_wo_rot;
+ u32 dst_h_rot;
+ /* input rotator */
+ u32 rl_w_wo_rot;
+ u32 rl_h_rot;
+};
+
+/*
+ * A structure of fimc context.
+ *
+ * @ippdrv: prepare initialization using ippdrv.
+ * @regs_res: register resources.
+ * @regs: memory mapped io registers.
+ * @lock: locking of operations.
+ * @sclk_fimc_clk: fimc source clock.
+ * @fimc_clk: fimc clock.
+ * @wb_clk: writeback a clock.
+ * @wb_b_clk: writeback b clock.
+ * @sc: scaler infomations.
+ * @capa: scaler capability.
+ * @odr: ordering of YUV.
+ * @ver: fimc version.
+ * @pol: porarity of writeback.
+ * @id: fimc id.
+ * @irq: irq number.
+ * @suspended: qos operations.
+ */
+struct fimc_context {
+ struct exynos_drm_ippdrv ippdrv;
+ struct resource *regs_res;
+ void __iomem *regs;
+ struct mutex lock;
+ struct clk *sclk_fimc_clk;
+ struct clk *fimc_clk;
+ struct clk *wb_clk;
+ struct clk *wb_b_clk;
+ struct fimc_scaler sc;
+ struct fimc_capability *capa;
+ enum exynos_drm_fimc_ver ver;
+ struct exynos_drm_fimc_pol pol;
+ int id;
+ int irq;
+ bool suspended;
+};
+
+struct fimc_capability fimc51_capa[FIMC_MAX_DEVS] = {
+ {
+ .in_hori = 4224,
+ .bypass = 8192,
+ .dst_h_wo_rot = 4224,
+ .dst_h_rot = 1920,
+ .rl_w_wo_rot = 8192,
+ .rl_h_rot = 1920,
+ }, {
+ .in_hori = 4224,
+ .bypass = 8192,
+ .dst_h_wo_rot = 4224,
+ .dst_h_rot = 1920,
+ .rl_w_wo_rot = 8192,
+ .rl_h_rot = 1920,
+ }, {
+ .in_hori = 4224,
+ .bypass = 8192,
+ .dst_h_wo_rot = 4224,
+ .dst_h_rot = 1920,
+ .rl_w_wo_rot = 8192,
+ .rl_h_rot = 1920,
+ }, {
+ .in_hori = 1920,
+ .bypass = 8192,
+ .dst_h_wo_rot = 1920,
+ .dst_h_rot = 1366,
+ .rl_w_wo_rot = 8192,
+ .rl_h_rot = 1366,
+ },
+};
+
+static void fimc_sw_reset(struct fimc_context *ctx, bool pattern)
+{
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:pattern[%d]\n", __func__, pattern);
+
+ cfg = fimc_read(EXYNOS_CISRCFMT);
+ cfg |= EXYNOS_CISRCFMT_ITU601_8BIT;
+ if (pattern)
+ cfg |= EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR;
+
+ fimc_write(cfg, EXYNOS_CISRCFMT);
+
+ /* s/w reset */
+ cfg = fimc_read(EXYNOS_CIGCTRL);
+ cfg |= (EXYNOS_CIGCTRL_SWRST);
+ fimc_write(cfg, EXYNOS_CIGCTRL);
+
+ /* s/w reset complete */
+ cfg = fimc_read(EXYNOS_CIGCTRL);
+ cfg &= ~EXYNOS_CIGCTRL_SWRST;
+ fimc_write(cfg, EXYNOS_CIGCTRL);
+
+ /* reset sequence */
+ fimc_write(0x0, EXYNOS_CIFCNTSEQ);
+}
+
+static void fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
+{
+ u32 camblk_cfg;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ camblk_cfg = readl(SYSREG_CAMERA_BLK);
+ camblk_cfg &= ~(SYSREG_FIMD0WB_DEST_MASK);
+ camblk_cfg |= ctx->id << (SYSREG_FIMD0WB_DEST_SHIFT);
+
+ writel(camblk_cfg, SYSREG_CAMERA_BLK);
+}
+
+static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
+{
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:wb[%d]\n", __func__, wb);
+
+ cfg = fimc_read(EXYNOS_CIGCTRL);
+ cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK |
+ EXYNOS_CIGCTRL_SELCAM_ITU_MASK |
+ EXYNOS_CIGCTRL_SELCAM_MIPI_MASK |
+ EXYNOS_CIGCTRL_SELCAM_FIMC_MASK |
+ EXYNOS_CIGCTRL_SELWB_CAMIF_MASK |
+ EXYNOS_CIGCTRL_SELWRITEBACK_MASK);
+
+ switch (wb) {
+ case FIMC_WB_A:
+ cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_A |
+ EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
+ break;
+ case FIMC_WB_B:
+ cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_B |
+ EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
+ break;
+ case FIMC_WB_NONE:
+ default:
+ cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A |
+ EXYNOS_CIGCTRL_SELWRITEBACK_A |
+ EXYNOS_CIGCTRL_SELCAM_MIPI_A |
+ EXYNOS_CIGCTRL_SELCAM_FIMC_ITU);
+ break;
+ }
+
+ fimc_write(cfg, EXYNOS_CIGCTRL);
+}
+
+static void fimc_set_polarity(struct fimc_context *ctx,
+ struct exynos_drm_fimc_pol *pol)
+{
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:inv_pclk[%d]inv_vsync[%d]\n",
+ __func__, pol->inv_pclk, pol->inv_vsync);
+ DRM_DEBUG_KMS("%s:inv_href[%d]inv_hsync[%d]\n",
+ __func__, pol->inv_href, pol->inv_hsync);
+
+ cfg = fimc_read(EXYNOS_CIGCTRL);
+ cfg &= ~(EXYNOS_CIGCTRL_INVPOLPCLK | EXYNOS_CIGCTRL_INVPOLVSYNC |
+ EXYNOS_CIGCTRL_INVPOLHREF | EXYNOS_CIGCTRL_INVPOLHSYNC);
+
+ if (pol->inv_pclk)
+ cfg |= EXYNOS_CIGCTRL_INVPOLPCLK;
+ if (pol->inv_vsync)
+ cfg |= EXYNOS_CIGCTRL_INVPOLVSYNC;
+ if (pol->inv_href)
+ cfg |= EXYNOS_CIGCTRL_INVPOLHREF;
+ if (pol->inv_hsync)
+ cfg |= EXYNOS_CIGCTRL_INVPOLHSYNC;
+
+ fimc_write(cfg, EXYNOS_CIGCTRL);
+}
+
+static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable)
+{
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
+
+ cfg = fimc_read(EXYNOS_CIGCTRL);
+ if (enable)
+ cfg |= EXYNOS_CIGCTRL_CAM_JPEG;
+ else
+ cfg &= ~EXYNOS_CIGCTRL_CAM_JPEG;
+
+ fimc_write(cfg, EXYNOS_CIGCTRL);
+}
+
+static void fimc_handle_irq(struct fimc_context *ctx, bool enable,
+ bool overflow, bool level)
+{
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__,
+ enable, overflow, level);
+
+ cfg = fimc_read(EXYNOS_CIGCTRL);
+ if (enable) {
+ cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_LEVEL);
+ cfg |= EXYNOS_CIGCTRL_IRQ_ENABLE;
+ if (overflow)
+ cfg |= EXYNOS_CIGCTRL_IRQ_OVFEN;
+ if (level)
+ cfg |= EXYNOS_CIGCTRL_IRQ_LEVEL;
+ } else
+ cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_ENABLE);
+
+ fimc_write(cfg, EXYNOS_CIGCTRL);
+}
+
+static void fimc_clear_irq(struct fimc_context *ctx)
+{
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ cfg = fimc_read(EXYNOS_CIGCTRL);
+ cfg |= EXYNOS_CIGCTRL_IRQ_CLR;
+ fimc_write(cfg, EXYNOS_CIGCTRL);
+}
+
+static bool fimc_check_ovf(struct fimc_context *ctx)
+{
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg, status, flag;
+
+ status = fimc_read(EXYNOS_CISTATUS);
+ flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB |
+ EXYNOS_CISTATUS_OVFICR;
+
+ DRM_DEBUG_KMS("%s:flag[0x%x]\n", __func__, flag);
+
+ if (status & flag) {
+ cfg = fimc_read(EXYNOS_CIWDOFST);
+ cfg |= (EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
+ EXYNOS_CIWDOFST_CLROVFICR);
+
+ fimc_write(cfg, EXYNOS_CIWDOFST);
+
+ cfg = fimc_read(EXYNOS_CIWDOFST);
+ cfg &= ~(EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
+ EXYNOS_CIWDOFST_CLROVFICR);
+
+ fimc_write(cfg, EXYNOS_CIWDOFST);
+
+ dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n",
+ ctx->id, status);
+ return true;
+ }
+
+ return false;
+}
+
+static bool fimc_check_frame_end(struct fimc_context *ctx)
+{
+ u32 cfg;
+
+ cfg = fimc_read(EXYNOS_CISTATUS);
+
+ DRM_DEBUG_KMS("%s:cfg[0x%x]\n", __func__, cfg);
+
+ if (!(cfg & EXYNOS_CISTATUS_FRAMEEND))
+ return false;
+
+ cfg &= ~(EXYNOS_CISTATUS_FRAMEEND);
+ fimc_write(cfg, EXYNOS_CISTATUS);
+
+ return true;
+}
+
+static int fimc_get_buf_id(struct fimc_context *ctx)
+{
+ u32 cfg;
+ int frame_cnt, buf_id;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ cfg = fimc_read(EXYNOS_CISTATUS2);
+ frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg);
+
+ if (frame_cnt == 0)
+ frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg);
+
+ DRM_DEBUG_KMS("%s:present[%d]before[%d]\n", __func__,
+ EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg),
+ EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg));
+
+ if (frame_cnt == 0) {
+ DRM_ERROR("failed to get frame count.\n");
+ return -EIO;
+ }
+
+ buf_id = frame_cnt - 1;
+ DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
+
+ return buf_id;
+}
+
+static void fimc_handle_lastend(struct fimc_context *ctx, bool enable)
+{
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
+
+ cfg = fimc_read(EXYNOS_CIOCTRL);
+ if (enable)
+ cfg |= EXYNOS_CIOCTRL_LASTENDEN;
+ else
+ cfg &= ~EXYNOS_CIOCTRL_LASTENDEN;
+
+ fimc_write(cfg, EXYNOS_CIOCTRL);
+}
+
+static int fimc_set_planar_addr(struct drm_exynos_ipp_buf_info *buf_info,
+ u32 fmt, struct drm_exynos_sz *sz)
+{
+ dma_addr_t *y_addr = &buf_info->base[EXYNOS_DRM_PLANAR_Y];
+ dma_addr_t *cb_addr = &buf_info->base[EXYNOS_DRM_PLANAR_CB];
+ dma_addr_t *cr_addr = &buf_info->base[EXYNOS_DRM_PLANAR_CR];
+ uint64_t y_ofs, cb_ofs, cr_ofs;
+
+ /*
+ * ToDo: check the buffer size between gem allocated buffers
+ * and each planar size.
+ */
+ switch (fmt) {
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV61:
+ y_ofs = sz->hsize * sz->vsize;
+ cb_ofs = y_ofs >> 1;
+ cr_ofs = 0;
+ break;
+ case DRM_FORMAT_NV12M:
+ y_ofs = ALIGN(ALIGN(sz->hsize, 16) *
+ ALIGN(sz->vsize, 16), SZ_2K);
+ cb_ofs = ALIGN(ALIGN(sz->hsize, 16) *
+ ALIGN(sz->vsize >> 1, 16), SZ_2K);
+ cr_ofs = 0;
+ break;
+ case DRM_FORMAT_NV12MT:
+ y_ofs = ALIGN(ALIGN(sz->hsize, 128) *
+ ALIGN(sz->vsize, 32), SZ_8K);
+ cb_ofs = ALIGN(ALIGN(sz->hsize, 128) *
+ ALIGN(sz->vsize >> 1, 32), SZ_8K);
+ cr_ofs = 0;
+ break;
+ case DRM_FORMAT_YUV410:
+ case DRM_FORMAT_YVU410:
+ case DRM_FORMAT_YUV411:
+ case DRM_FORMAT_YVU411:
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_YUV422:
+ case DRM_FORMAT_YVU422:
+ case DRM_FORMAT_YUV444:
+ case DRM_FORMAT_YVU444:
+ case DRM_FORMAT_YUV420M:
+ y_ofs = sz->hsize * sz->vsize;
+ cb_ofs = cr_ofs = y_ofs >> 2;
+ break;
+ default:
+ y_ofs = cb_ofs = cr_ofs = 0;
+ break;
+ }
+
+ if (y_ofs && *y_addr) {
+ *cb_addr = *y_addr + y_ofs;
+
+ if (cb_ofs && *cb_addr)
+ *cr_addr = *cb_addr + cb_ofs;
+ }
+
+ return 0;
+}
+
+static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
+{
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+
+ /* RGB */
+ cfg = fimc_read(EXYNOS_CISCCTRL);
+ cfg &= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK;
+
+ switch (fmt) {
+ case DRM_FORMAT_RGB565:
+ cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565;
+ fimc_write(cfg, EXYNOS_CISCCTRL);
+ return 0;
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_XRGB8888:
+ cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888;
+ fimc_write(cfg, EXYNOS_CISCCTRL);
+ return 0;
+ default:
+ /* bypass */
+ break;
+ }
+
+ /* YUV */
+ cfg = fimc_read(EXYNOS_MSCTRL);
+ cfg &= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK |
+ EXYNOS_MSCTRL_C_INT_IN_2PLANE |
+ EXYNOS_MSCTRL_ORDER422_YCBYCR);
+
+ switch (fmt) {
+ case DRM_FORMAT_YUYV:
+ cfg |= EXYNOS_MSCTRL_ORDER422_YCBYCR;
+ break;
+ case DRM_FORMAT_YVYU:
+ cfg |= EXYNOS_MSCTRL_ORDER422_YCRYCB;
+ break;
+ case DRM_FORMAT_UYVY:
+ cfg |= EXYNOS_MSCTRL_ORDER422_CBYCRY;
+ break;
+ case DRM_FORMAT_VYUY:
+ case DRM_FORMAT_YUV444:
+ cfg |= EXYNOS_MSCTRL_ORDER422_CRYCBY;
+ break;
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV61:
+ cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB |
+ EXYNOS_MSCTRL_C_INT_IN_2PLANE);
+ break;
+ case DRM_FORMAT_YUV422:
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ cfg |= EXYNOS_MSCTRL_C_INT_IN_3PLANE;
+ break;
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV12M:
+ case DRM_FORMAT_NV12MT:
+ case DRM_FORMAT_NV16:
+ cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR |
+ EXYNOS_MSCTRL_C_INT_IN_2PLANE);
+ break;
+ default:
+ dev_err(ippdrv->dev, "inavlid source yuv order 0x%x.\n", fmt);
+ return -EINVAL;
+ }
+
+ fimc_write(cfg, EXYNOS_MSCTRL);
+
+ return 0;
+}
+
+static int fimc_src_set_fmt(struct device *dev, u32 fmt)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+
+ cfg = fimc_read(EXYNOS_MSCTRL);
+ cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB;
+
+ switch (fmt) {
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_XRGB8888:
+ cfg |= EXYNOS_MSCTRL_INFORMAT_RGB;
+ break;
+ case DRM_FORMAT_YUV444:
+ cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
+ break;
+ case DRM_FORMAT_YUYV:
+ case DRM_FORMAT_YVYU:
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_VYUY:
+ cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE;
+ break;
+ case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV61:
+ case DRM_FORMAT_YUV422:
+ cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422;
+ break;
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV12M:
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV12MT:
+ cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
+ break;
+ default:
+ dev_err(ippdrv->dev, "inavlid source format 0x%x.\n", fmt);
+ return -EINVAL;
+ }
+
+ fimc_write(cfg, EXYNOS_MSCTRL);
+
+ cfg = fimc_read(EXYNOS_CIDMAPARAM);
+ cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK;
+
+ if (fmt == DRM_FORMAT_NV12MT)
+ cfg |= EXYNOS_CIDMAPARAM_R_MODE_64X32;
+ else
+ cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR;
+
+ fimc_write(cfg, EXYNOS_CIDMAPARAM);
+
+ return fimc_src_set_fmt_order(ctx, fmt);
+}
+
+static int fimc_src_set_transf(struct device *dev,
+ enum drm_exynos_degree degree,
+ enum drm_exynos_flip flip)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
+ degree, flip);
+
+ cfg = fimc_read(EXYNOS_MSCTRL);
+ cfg &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR |
+ EXYNOS_MSCTRL_FLIP_Y_MIRROR);
+ cfg &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
+
+ switch (degree) {
+ case EXYNOS_DRM_DEGREE_0:
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
+ if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
+ break;
+ case EXYNOS_DRM_DEGREE_90:
+ cfg |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
+ if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
+ break;
+ case EXYNOS_DRM_DEGREE_180:
+ cfg |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
+ EXYNOS_MSCTRL_FLIP_Y_MIRROR);
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
+ if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
+ break;
+ case EXYNOS_DRM_DEGREE_270:
+ cfg |= (EXYNOS_CITRGFMT_INROT90_CLOCKWISE |
+ EXYNOS_MSCTRL_FLIP_X_MIRROR |
+ EXYNOS_MSCTRL_FLIP_Y_MIRROR);
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
+ if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
+ break;
+ default:
+ dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
+ return -EINVAL;
+ }
+
+ fimc_write(cfg, EXYNOS_MSCTRL);
+
+ return (cfg & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) ? 1 : 0;
+}
+
+static int fimc_set_window(struct fimc_context *ctx,
+ struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
+{
+ u32 cfg, h1, h2, v1, v2;
+
+ /* cropped image */
+ h1 = pos->x;
+ h2 = sz->hsize - pos->w - pos->x;
+ v1 = pos->y;
+ v2 = sz->vsize - pos->h - pos->y;
+
+ DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
+ __func__, pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize);
+ DRM_DEBUG_KMS("%s:h1[%d]h2[%d]v1[%d]v2[%d]\n", __func__,
+ h1, h2, v1, v2);
+
+ /*
+ * set window offset 1, 2 size
+ * check figure 43-21 in user manual
+ */
+ cfg = fimc_read(EXYNOS_CIWDOFST);
+ cfg &= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK |
+ EXYNOS_CIWDOFST_WINVEROFST_MASK);
+ cfg |= (EXYNOS_CIWDOFST_WINHOROFST(h1) |
+ EXYNOS_CIWDOFST_WINVEROFST(v1));
+ cfg |= EXYNOS_CIWDOFST_WINOFSEN;
+ fimc_write(cfg, EXYNOS_CIWDOFST);
+
+ cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) |
+ EXYNOS_CIWDOFST2_WINVEROFST2(v2));
+ fimc_write(cfg, EXYNOS_CIWDOFST2);
+
+ return 0;
+}
+
+static int fimc_src_set_size(struct device *dev, int swap,
+ struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ struct drm_exynos_ipp_property *property = ippdrv->property;
+ struct drm_exynos_ipp_config *config =
+ &property->config[EXYNOS_DRM_OPS_SRC];
+ struct drm_exynos_pos img_pos = *pos;
+ struct drm_exynos_sz img_sz = *sz;
+ u32 cfg;
+
+ /* ToDo: check width and height */
+
+ DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
+ __func__, swap, sz->hsize, sz->vsize);
+
+ /* original size */
+ cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) |
+ EXYNOS_ORGISIZE_VERTICAL(img_sz.vsize));
+
+ fimc_write(cfg, EXYNOS_ORGISIZE);
+
+ DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", __func__,
+ pos->x, pos->y, pos->w, pos->h);
+
+ if (swap) {
+ img_pos.w = pos->h;
+ img_pos.h = pos->w;
+ img_sz.hsize = sz->vsize;
+ img_sz.vsize = sz->hsize;
+ }
+
+ /* set input DMA image size */
+ cfg = fimc_read(EXYNOS_CIREAL_ISIZE);
+ cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK |
+ EXYNOS_CIREAL_ISIZE_WIDTH_MASK);
+ cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(img_sz.hsize) |
+ EXYNOS_CIREAL_ISIZE_HEIGHT(img_sz.vsize));
+ fimc_write(cfg, EXYNOS_CIREAL_ISIZE);
+
+ /*
+ * set input FIFO image size
+ * for now, we support only ITU601 8 bit mode
+ */
+ cfg = (EXYNOS_CISRCFMT_ITU601_8BIT |
+ EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz.hsize) |
+ EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz.vsize));
+ fimc_write(cfg, EXYNOS_CISRCFMT);
+
+ config->sz = img_sz;
+ config->pos = img_pos;
+
+ return fimc_set_window(ctx, &img_pos, &img_sz);
+}
+
+static int fimc_src_set_addr(struct device *dev,
+ struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
+ enum drm_exynos_ipp_buf_ctrl buf_ctrl)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ struct drm_exynos_ipp_property *property = ippdrv->property;
+ struct drm_exynos_ipp_config *config =
+ &property->config[EXYNOS_DRM_OPS_SRC];
+ int ret;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__,
+ buf_id, buf_ctrl);
+
+ if (buf_id > FIMC_MAX_SRC) {
+ dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
+ return -ENOMEM;
+ }
+
+ /* address register set */
+ switch (buf_ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ case IPP_BUF_CTRL_DEQUEUE:
+ ret = fimc_set_planar_addr(buf_info, config->fmt, &config->sz);
+
+ if (ret) {
+ dev_err(dev, "failed to set plane addr.\n");
+ return ret;
+ }
+
+ fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
+ EXYNOS_CIIYSA(buf_id));
+
+ if (config->fmt == DRM_FORMAT_YVU420) {
+ fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
+ EXYNOS_CIICBSA(buf_id));
+ fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
+ EXYNOS_CIICRSA(buf_id));
+ } else {
+ fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
+ EXYNOS_CIICBSA(buf_id));
+ fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
+ EXYNOS_CIICRSA(buf_id));
+ }
+ break;
+ default:
+ /* bypass */
+ break;
+ }
+
+ return 0;
+}
+
+static struct exynos_drm_ipp_ops fimc_src_ops = {
+ .set_fmt = fimc_src_set_fmt,
+ .set_transf = fimc_src_set_transf,
+ .set_size = fimc_src_set_size,
+ .set_addr = fimc_src_set_addr,
+};
+
+static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
+{
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+
+ /* RGB */
+ cfg = fimc_read(EXYNOS_CISCCTRL);
+ cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK;
+
+ switch (fmt) {
+ case DRM_FORMAT_RGB565:
+ cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565;
+ fimc_write(cfg, EXYNOS_CISCCTRL);
+ return 0;
+ case DRM_FORMAT_RGB888:
+ cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888;
+ fimc_write(cfg, EXYNOS_CISCCTRL);
+ return 0;
+ case DRM_FORMAT_XRGB8888:
+ cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 |
+ EXYNOS_CISCCTRL_EXTRGB_EXTENSION);
+ fimc_write(cfg, EXYNOS_CISCCTRL);
+ break;
+ default:
+ /* bypass */
+ break;
+ }
+
+ /* YUV */
+ cfg = fimc_read(EXYNOS_CIOCTRL);
+ cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK |
+ EXYNOS_CIOCTRL_ORDER422_MASK |
+ EXYNOS_CIOCTRL_YCBCR_PLANE_MASK);
+
+ switch (fmt) {
+ case DRM_FORMAT_XRGB8888:
+ cfg |= EXYNOS_CIOCTRL_ALPHA_OUT;
+ break;
+ case DRM_FORMAT_YUYV:
+ cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR;
+ break;
+ case DRM_FORMAT_YVYU:
+ cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB;
+ break;
+ case DRM_FORMAT_UYVY:
+ cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY;
+ break;
+ case DRM_FORMAT_VYUY:
+ cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY;
+ break;
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV61:
+ cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB;
+ cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
+ break;
+ case DRM_FORMAT_YUV422:
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE;
+ break;
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV12M:
+ case DRM_FORMAT_NV12MT:
+ case DRM_FORMAT_NV16:
+ cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR;
+ cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
+ break;
+ default:
+ dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
+ return -EINVAL;
+ }
+
+ fimc_write(cfg, EXYNOS_CIOCTRL);
+
+ return 0;
+}
+
+static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+
+ cfg = fimc_read(EXYNOS_CIEXTEN);
+
+ if (fmt == DRM_FORMAT_AYUV) {
+ cfg |= EXYNOS_CIEXTEN_YUV444_OUT;
+ fimc_write(cfg, EXYNOS_CIEXTEN);
+ } else {
+ cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT;
+ fimc_write(cfg, EXYNOS_CIEXTEN);
+
+ cfg = fimc_read(EXYNOS_CITRGFMT);
+ cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK;
+
+ switch (fmt) {
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_XRGB8888:
+ cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB;
+ break;
+ case DRM_FORMAT_YUYV:
+ case DRM_FORMAT_YVYU:
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_VYUY:
+ cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
+ break;
+ case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV61:
+ case DRM_FORMAT_YUV422:
+ cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422;
+ break;
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV12M:
+ case DRM_FORMAT_NV12MT:
+ case DRM_FORMAT_NV21:
+ cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420;
+ break;
+ default:
+ dev_err(ippdrv->dev, "inavlid target format 0x%x.\n",
+ fmt);
+ return -EINVAL;
+ }
+
+ fimc_write(cfg, EXYNOS_CITRGFMT);
+ }
+
+ cfg = fimc_read(EXYNOS_CIDMAPARAM);
+ cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK;
+
+ if (fmt == DRM_FORMAT_NV12MT)
+ cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32;
+ else
+ cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR;
+
+ fimc_write(cfg, EXYNOS_CIDMAPARAM);
+
+ return fimc_dst_set_fmt_order(ctx, fmt);
+}
+
+static int fimc_dst_set_transf(struct device *dev,
+ enum drm_exynos_degree degree,
+ enum drm_exynos_flip flip)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
+ degree, flip);
+
+ cfg = fimc_read(EXYNOS_CITRGFMT);
+ cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK;
+ cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
+
+ switch (degree) {
+ case EXYNOS_DRM_DEGREE_0:
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
+ if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
+ break;
+ case EXYNOS_DRM_DEGREE_90:
+ cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
+ if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
+ break;
+ case EXYNOS_DRM_DEGREE_180:
+ cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR |
+ EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
+ if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
+ break;
+ case EXYNOS_DRM_DEGREE_270:
+ cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE |
+ EXYNOS_CITRGFMT_FLIP_X_MIRROR |
+ EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
+ if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
+ break;
+ default:
+ dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
+ return -EINVAL;
+ }
+
+ fimc_write(cfg, EXYNOS_CITRGFMT);
+
+ return (cfg & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) ? 1 : 0;
+}
+
+static int fimc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift)
+{
+ DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
+
+ if (src >= dst * 64) {
+ DRM_ERROR("failed to make ratio and shift.\n");
+ return -EINVAL;
+ } else if (src >= dst * 32) {
+ *ratio = 32;
+ *shift = 5;
+ } else if (src >= dst * 16) {
+ *ratio = 16;
+ *shift = 4;
+ } else if (src >= dst * 8) {
+ *ratio = 8;
+ *shift = 3;
+ } else if (src >= dst * 4) {
+ *ratio = 4;
+ *shift = 2;
+ } else if (src >= dst * 2) {
+ *ratio = 2;
+ *shift = 1;
+ } else {
+ *ratio = 1;
+ *shift = 0;
+ }
+
+ return 0;
+}
+
+static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
+ struct drm_exynos_pos *src, struct drm_exynos_pos *dst)
+{
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg, shfactor;
+ u32 pre_dst_width, pre_dst_height;
+ u32 pre_hratio, hfactor, pre_vratio, vfactor;
+ int ret = 0;
+
+ ret = fimc_get_ratio_shift(src->w, dst->w, &pre_hratio, &hfactor);
+ if (ret) {
+ dev_err(ippdrv->dev, "failed to get ratio horizontal.\n");
+ return ret;
+ }
+
+ ret = fimc_get_ratio_shift(src->h, dst->h, &pre_vratio, &vfactor);
+ if (ret) {
+ dev_err(ippdrv->dev, "failed to get ratio vertical.\n");
+ return ret;
+ }
+
+ pre_dst_width = src->w / pre_hratio;
+ pre_dst_height = src->h / pre_vratio;
+ DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__,
+ pre_dst_width, pre_dst_height);
+ DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
+ __func__, pre_hratio, hfactor, pre_vratio, vfactor);
+
+ sc->hratio = (src->w << 14) / (dst->w << hfactor);
+ sc->vratio = (src->h << 14) / (dst->h << vfactor);
+ sc->up_h = (dst->w >= src->w) ? true : false;
+ sc->up_v = (dst->h >= src->h) ? true : false;
+ DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
+ __func__, sc->hratio, sc->vratio, sc->up_h, sc->up_v);
+
+ shfactor = 10 - (hfactor + vfactor);
+ DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__, shfactor);
+
+ cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) |
+ EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio) |
+ EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio));
+ fimc_write(cfg, EXYNOS_CISCPRERATIO);
+
+ cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) |
+ EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height));
+ fimc_write(cfg, EXYNOS_CISCPREDST);
+
+ return ret;
+}
+
+static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
+{
+ u32 cfg, cfg_ext;
+
+ DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
+ __func__, sc->range, sc->bypass, sc->up_h, sc->up_v);
+ DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n",
+ __func__, sc->hratio, sc->vratio);
+
+ cfg = fimc_read(EXYNOS_CISCCTRL);
+ cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS |
+ EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V |
+ EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK |
+ EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK |
+ EXYNOS_CISCCTRL_CSCR2Y_WIDE |
+ EXYNOS_CISCCTRL_CSCY2R_WIDE);
+
+ if (sc->range)
+ cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE |
+ EXYNOS_CISCCTRL_CSCY2R_WIDE);
+ if (sc->bypass)
+ cfg |= EXYNOS_CISCCTRL_SCALERBYPASS;
+ if (sc->up_h)
+ cfg |= EXYNOS_CISCCTRL_SCALEUP_H;
+ if (sc->up_v)
+ cfg |= EXYNOS_CISCCTRL_SCALEUP_V;
+
+ cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) |
+ EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6)));
+ fimc_write(cfg, EXYNOS_CISCCTRL);
+
+ cfg_ext = fimc_read(EXYNOS_CIEXTEN);
+ cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK;
+ cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK;
+ cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) |
+ EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio));
+ fimc_write(cfg_ext, EXYNOS_CIEXTEN);
+}
+
+static int fimc_dst_set_size(struct device *dev, int swap,
+ struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ struct drm_exynos_ipp_property *property = ippdrv->property;
+ struct drm_exynos_ipp_config *config =
+ &property->config[EXYNOS_DRM_OPS_DST];
+ struct drm_exynos_pos img_pos = *pos;
+ struct drm_exynos_sz img_sz = *sz;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
+ __func__, swap, sz->hsize, sz->vsize);
+
+ /* original size */
+ cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) |
+ EXYNOS_ORGOSIZE_VERTICAL(img_sz.vsize));
+
+ fimc_write(cfg, EXYNOS_ORGOSIZE);
+
+ DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n",
+ __func__, pos->x, pos->y, pos->w, pos->h);
+
+ /* CSC ITU */
+ cfg = fimc_read(EXYNOS_CIGCTRL);
+ cfg &= ~EXYNOS_CIGCTRL_CSC_MASK;
+
+ if (sz->hsize >= FIMC_WIDTH_ITU_709)
+ cfg |= EXYNOS_CIGCTRL_CSC_ITU709;
+ else
+ cfg |= EXYNOS_CIGCTRL_CSC_ITU601;
+
+ fimc_write(cfg, EXYNOS_CIGCTRL);
+
+ if (swap) {
+ img_pos.w = pos->h;
+ img_pos.h = pos->w;
+ img_sz.hsize = sz->vsize;
+ img_sz.vsize = sz->hsize;
+ }
+
+ /* target image size */
+ cfg = fimc_read(EXYNOS_CITRGFMT);
+ cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK |
+ EXYNOS_CITRGFMT_TARGETV_MASK);
+ cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos.w) |
+ EXYNOS_CITRGFMT_TARGETVSIZE(img_pos.h));
+ fimc_write(cfg, EXYNOS_CITRGFMT);
+
+ /* target area */
+ cfg = EXYNOS_CITAREA_TARGET_AREA(img_pos.w * img_pos.h);
+ fimc_write(cfg, EXYNOS_CITAREA);
+
+ /* ToDo: Move Scaler in this line and YUV */
+ config->sz = img_sz;
+ config->pos = img_pos;
+
+ /* offset Y(RGB), Cb, Cr */
+ cfg = (EXYNOS_CIOYOFF_HORIZONTAL(img_pos.x) |
+ EXYNOS_CIOYOFF_VERTICAL(img_pos.y));
+ fimc_write(cfg, EXYNOS_CIOYOFF);
+ cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos.x) |
+ EXYNOS_CIOCBOFF_VERTICAL(img_pos.y));
+ fimc_write(cfg, EXYNOS_CIOCBOFF);
+ cfg = (EXYNOS_CIOCROFF_HORIZONTAL(img_pos.x) |
+ EXYNOS_CIOCROFF_VERTICAL(img_pos.y));
+ fimc_write(cfg, EXYNOS_CIOCROFF);
+
+ return 0;
+}
+
+static int fimc_dst_get_buf_seq(struct fimc_context *ctx)
+{
+ u32 cfg, i, buf_num = 0;
+ u32 mask = 0x00000001;
+
+ cfg = fimc_read(EXYNOS_CIFCNTSEQ);
+
+ for (i = 0; i < FIMC_REG_SZ; i++)
+ if (cfg & (mask << i))
+ buf_num++;
+
+ DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
+
+ return buf_num;
+}
+
+static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
+ enum drm_exynos_ipp_buf_ctrl buf_ctrl)
+{
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ bool enable;
+ u32 cfg;
+ u32 mask = 0x00000001 << buf_id;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__,
+ buf_id, buf_ctrl);
+
+ /* mask register set */
+ cfg = fimc_read(EXYNOS_CIFCNTSEQ);
+
+ switch (buf_ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ enable = true;
+ break;
+ case IPP_BUF_CTRL_DEQUEUE:
+ enable = false;
+ break;
+ default:
+ dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n");
+ return -EINVAL;
+ }
+
+ /* sequence id */
+ cfg &= (~mask);
+ cfg |= (enable << buf_id);
+ fimc_write(cfg, EXYNOS_CIFCNTSEQ);
+
+ /* interrupt enable */
+ if (buf_ctrl == IPP_BUF_CTRL_QUEUE &&
+ fimc_dst_get_buf_seq(ctx) >= FIMC_BUF_START)
+ fimc_handle_irq(ctx, true, false, true);
+
+ /* interrupt disable */
+ if (buf_ctrl == IPP_BUF_CTRL_DEQUEUE &&
+ fimc_dst_get_buf_seq(ctx) <= FIMC_BUF_STOP)
+ fimc_handle_irq(ctx, false, false, true);
+
+ return 0;
+}
+
+static int fimc_dst_set_addr(struct device *dev,
+ struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
+ enum drm_exynos_ipp_buf_ctrl buf_ctrl)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ struct drm_exynos_ipp_property *property = ippdrv->property;
+ struct drm_exynos_ipp_config *config =
+ &property->config[EXYNOS_DRM_OPS_DST];
+ int ret;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__,
+ buf_id, buf_ctrl);
+
+ if (buf_id > FIMC_MAX_DST) {
+ dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
+ return -ENOMEM;
+ }
+
+ /* address register set */
+ switch (buf_ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ case IPP_BUF_CTRL_DEQUEUE:
+ ret = fimc_set_planar_addr(buf_info, config->fmt, &config->sz);
+
+ if (ret) {
+ dev_err(dev, "failed to set plane addr.\n");
+ return ret;
+ }
+
+ fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
+ EXYNOS_CIOYSA(buf_id));
+
+ if (config->fmt == DRM_FORMAT_YVU420) {
+ fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
+ EXYNOS_CIOCBSA(buf_id));
+ fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
+ EXYNOS_CIOCRSA(buf_id));
+ } else {
+ fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
+ EXYNOS_CIOCBSA(buf_id));
+ fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
+ EXYNOS_CIOCRSA(buf_id));
+ }
+ break;
+ default:
+ /* bypass */
+ break;
+ }
+
+ return fimc_dst_set_buf_seq(ctx, buf_id, buf_ctrl);
+}
+
+static struct exynos_drm_ipp_ops fimc_dst_ops = {
+ .set_fmt = fimc_dst_set_fmt,
+ .set_transf = fimc_dst_set_transf,
+ .set_size = fimc_dst_set_size,
+ .set_addr = fimc_dst_set_addr,
+};
+
+static int fimc_power_on(struct fimc_context *ctx, bool enable)
+{
+ DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
+
+ if (enable) {
+ clk_enable(ctx->sclk_fimc_clk);
+ clk_enable(ctx->fimc_clk);
+ clk_enable(ctx->wb_clk);
+ /* ToDo : wb_b_clk */
+ ctx->suspended = false;
+ } else {
+ clk_disable(ctx->sclk_fimc_clk);
+ clk_disable(ctx->fimc_clk);
+ clk_disable(ctx->wb_clk);
+ /* ToDo : wb_b_clk */
+ ctx->suspended = true;
+ }
+
+ return 0;
+}
+
+static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
+{
+ struct fimc_context *ctx = dev_id;
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ int buf_id;
+ u32 status1, status2;
+
+ DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__, ctx->id);
+
+ /* ToDo: must be remove debug routine */
+ status1 = fimc_read(EXYNOS_CISTATUS);
+ status2 = fimc_read(EXYNOS_CISTATUS2);
+ DRM_DEBUG_KMS("%s:status1[0x%x]status2[0x%x]\n",
+ __func__, status1, status2);
+
+ fimc_clear_irq(ctx);
+ if (fimc_check_ovf(ctx))
+ return IRQ_NONE;
+
+ if (!fimc_check_frame_end(ctx))
+ return IRQ_NONE;
+
+ if (list_empty(&ippdrv->event_list)) {
+ DRM_DEBUG_KMS("%s:event list empty. so ignore.\n", __func__);
+
+ return IRQ_NONE;
+ }
+
+ buf_id = fimc_get_buf_id(ctx);
+ if (buf_id < 0)
+ return IRQ_HANDLED;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
+
+ if (fimc_dst_set_buf_seq(ctx, buf_id,
+ IPP_BUF_CTRL_DEQUEUE) < 0) {
+ DRM_ERROR("failed to dequeue.\n");
+
+ return IRQ_HANDLED;
+ }
+
+ ipp_send_event_handler(ippdrv, buf_id);
+
+ if (fimc_dst_get_buf_seq(ctx) <= FIMC_BUF_STOP)
+ fimc_handle_irq(ctx, false, false, true);
+
+ return IRQ_HANDLED;
+}
+
+static int fimc_ippdrv_check_property(struct device *dev,
+ struct drm_exynos_ipp_property *property)
+{
+ /* ToDo: check valid using property information */
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ return 0;
+}
+
+static int fimc_ippdrv_reset(struct device *dev)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ /* reset h/w block */
+ fimc_sw_reset(ctx, false);
+
+ /* reset scaler capability */
+ memset(&ctx->sc, 0x0, sizeof(ctx->sc));
+
+ return 0;
+}
+
+static int fimc_check_prepare(struct fimc_context *ctx)
+{
+ /* ToDo: check prepare using read register */
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ return 0;
+}
+
+static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ struct drm_exynos_ipp_property *property = ippdrv->property;
+ struct drm_exynos_ipp_config *config;
+ struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX];
+ int ret, i;
+ int enable = 1;
+ u32 cfg0, cfg1;
+
+ DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
+
+ ret = fimc_check_prepare(ctx);
+ if (ret) {
+ dev_err(dev, "failed to check prepare.\n");
+ return ret;
+ }
+
+ ippdrv->cmd = cmd;
+ fimc_handle_irq(ctx, true, false, true);
+
+ /* ToDo: window size, prescaler config */
+ for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) {
+ config = &property->config[i];
+ img_pos[i] = config->pos;
+ }
+
+ ret = fimc_set_prescaler(ctx, &ctx->sc,
+ &img_pos[EXYNOS_DRM_OPS_SRC],
+ &img_pos[EXYNOS_DRM_OPS_DST]);
+ if (ret) {
+ dev_err(dev, "failed to set precalser.\n");
+ return ret;
+ }
+
+ /* If set ture, we can save jpeg about screen */
+ fimc_handle_jpeg(ctx, false);
+ fimc_set_scaler(ctx, &ctx->sc);
+ fimc_set_polarity(ctx, &ctx->pol);
+
+ switch (cmd) {
+ case IPP_CMD_M2M:
+ fimc_set_type_ctrl(ctx, FIMC_WB_NONE);
+ fimc_handle_lastend(ctx, false);
+
+ /* setup dma */
+ cfg0 = fimc_read(EXYNOS_MSCTRL);
+ cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK;
+ cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY;
+ fimc_write(cfg0, EXYNOS_MSCTRL);
+ break;
+ case IPP_CMD_WB:
+ fimc_set_type_ctrl(ctx, FIMC_WB_A);
+ fimc_handle_lastend(ctx, true);
+
+ /* setup FIMD */
+ fimc_set_camblk_fimd0_wb(ctx);
+ exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)enable);
+ break;
+ case IPP_CMD_OUTPUT:
+ default:
+ ret = -EINVAL;
+ dev_err(dev, "invalid operations.\n");
+ return ret;
+ }
+
+ /* Reset status */
+ fimc_write(0x0, EXYNOS_CISTATUS);
+
+ cfg0 = fimc_read(EXYNOS_CIIMGCPT);
+ cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC;
+ cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC;
+
+ /* Scaler */
+ cfg1 = fimc_read(EXYNOS_CISCCTRL);
+ cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK;
+ cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE |
+ EXYNOS_CISCCTRL_SCALERSTART);
+
+ fimc_write(cfg1, EXYNOS_CISCCTRL);
+
+ /* Enable image capture*/
+ cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN;
+ fimc_write(cfg0, EXYNOS_CIIMGCPT);
+
+ /* Disable frame end irq */
+ cfg0 = fimc_read(EXYNOS_CIGCTRL);
+ cfg0 &= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE;
+ fimc_write(cfg0, EXYNOS_CIGCTRL);
+
+ cfg0 = fimc_read(EXYNOS_CIOCTRL);
+ cfg0 &= ~EXYNOS_CIOCTRL_WEAVE_MASK;
+ fimc_write(cfg0, EXYNOS_CIOCTRL);
+
+ /* ToDo: m2m start errata - refer fimd */
+ if (cmd == IPP_CMD_M2M) {
+ cfg0 = fimc_read(EXYNOS_MSCTRL);
+ cfg0 |= EXYNOS_MSCTRL_ENVID;
+ fimc_write(cfg0, EXYNOS_MSCTRL);
+
+ cfg0 = fimc_read(EXYNOS_MSCTRL);
+ cfg0 |= EXYNOS_MSCTRL_ENVID;
+ fimc_write(cfg0, EXYNOS_MSCTRL);
+ }
+
+ return 0;
+}
+
+static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ int enable = 0;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
+
+ switch (cmd) {
+ case IPP_CMD_M2M:
+ /* Source clear */
+ cfg = fimc_read(EXYNOS_MSCTRL);
+ cfg &= ~EXYNOS_MSCTRL_INPUT_MASK;
+ cfg &= ~EXYNOS_MSCTRL_ENVID;
+ fimc_write(cfg, EXYNOS_MSCTRL);
+ break;
+ case IPP_CMD_WB:
+ exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)enable);
+ break;
+ case IPP_CMD_OUTPUT:
+ default:
+ dev_err(dev, "invalid operations.\n");
+ break;
+ }
+
+ ippdrv->cmd = IPP_CMD_NONE;
+ fimc_handle_irq(ctx, false, false, true);
+
+ /* reset sequence */
+ fimc_write(0x0, EXYNOS_CIFCNTSEQ);
+
+ /* Scaler disable */
+ cfg = fimc_read(EXYNOS_CISCCTRL);
+ cfg &= ~EXYNOS_CISCCTRL_SCALERSTART;
+ fimc_write(cfg, EXYNOS_CISCCTRL);
+
+ /* Disable image capture */
+ cfg = fimc_read(EXYNOS_CIIMGCPT);
+ cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
+ fimc_write(cfg, EXYNOS_CIIMGCPT);
+
+ /* Enable frame end irq */
+ cfg = fimc_read(EXYNOS_CIGCTRL);
+ cfg |= EXYNOS_CIGCTRL_IRQ_END_DISABLE;
+ fimc_write(cfg, EXYNOS_CIGCTRL);
+}
+
+static struct fimc_capability *fimc_get_capability(
+ enum exynos_drm_fimc_ver ver)
+{
+ struct fimc_capability *capa;
+
+ DRM_DEBUG_KMS("%s:ver[0x%x]\n", __func__, ver);
+
+ /* ToDo: version check */
+ switch (ver) {
+ case FIMC_EXYNOS_4412:
+ default:
+ capa = fimc51_capa;
+ break;
+ }
+
+ return capa;
+}
+
+#ifdef CONFIG_SLP_DISP_DEBUG
+static int fimc_read_reg(struct fimc_context *ctx, char *buf)
+{
+ u32 cfg;
+ int i;
+ int pos = 0;
+
+ pos += sprintf(buf+pos, "0x%.8x | ", FIMC_BASE_REG(ctx->id));
+ for (i = 1; i < FIMC_MAX_REG + 1; i++) {
+ cfg = fimc_read((i-1) * sizeof(u32));
+ pos += sprintf(buf+pos, "0x%.8x ", cfg);
+ if (i % 4 == 0)
+ pos += sprintf(buf+pos, "\n0x%.8x | ",
+ FIMC_BASE_REG(ctx->id) + (i * sizeof(u32)));
+ }
+
+ pos += sprintf(buf+pos, "\n");
+
+ return pos;
+}
+
+static ssize_t show_read_reg(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+
+ if (!ctx->regs) {
+ dev_err(dev, "failed to get current register.\n");
+ return -EINVAL;
+ }
+
+ return fimc_read_reg(ctx, buf);
+}
+
+static struct device_attribute device_attrs[] = {
+ __ATTR(read_reg, S_IRUGO, show_read_reg, NULL),
+};
+#endif
+
+static int __devinit fimc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct fimc_context *ctx;
+ struct clk *parent_clk;
+ struct resource *res;
+ struct exynos_drm_ippdrv *ippdrv;
+ struct exynos_drm_fimc_pdata *pdata;
+ int ret = -EINVAL;
+#ifdef CONFIG_SLP_DISP_DEBUG
+ int i;
+#endif
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(dev, "no platform data specified.\n");
+ return -EINVAL;
+ }
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ /* clock control */
+ ctx->sclk_fimc_clk = clk_get(dev, "sclk_fimc");
+ if (IS_ERR(ctx->sclk_fimc_clk)) {
+ dev_err(dev, "failed to get src fimc clock.\n");
+ ret = PTR_ERR(ctx->sclk_fimc_clk);
+ goto err_ctx;
+ }
+ clk_enable(ctx->sclk_fimc_clk);
+
+ ctx->fimc_clk = clk_get(dev, "fimc");
+ if (IS_ERR(ctx->fimc_clk)) {
+ dev_err(dev, "failed to get fimc clock.\n");
+ ret = PTR_ERR(ctx->fimc_clk);
+ clk_put(ctx->sclk_fimc_clk);
+ goto err_ctx;
+ }
+
+ ctx->wb_clk = clk_get(dev, "pxl_async0");
+ if (IS_ERR(ctx->wb_clk)) {
+ dev_err(dev, "failed to get writeback a clock.\n");
+ ret = PTR_ERR(ctx->wb_clk);
+ clk_put(ctx->sclk_fimc_clk);
+ clk_put(ctx->fimc_clk);
+ goto err_ctx;
+ }
+
+ ctx->wb_b_clk = clk_get(dev, "pxl_async1");
+ if (IS_ERR(ctx->wb_b_clk)) {
+ dev_err(dev, "failed to get writeback b clock.\n");
+ ret = PTR_ERR(ctx->wb_b_clk);
+ clk_put(ctx->sclk_fimc_clk);
+ clk_put(ctx->fimc_clk);
+ clk_put(ctx->wb_clk);
+ goto err_ctx;
+ }
+
+ if (pdata->ver == FIMC_EXYNOS_4212 ||
+ pdata->ver == FIMC_EXYNOS_4412)
+ parent_clk = clk_get(dev, "mout_mpll_user");
+ else
+ parent_clk = clk_get(dev, "mout_mpll");
+
+ if (IS_ERR(parent_clk)) {
+ dev_err(dev, "failed to get parent clock.\n");
+ ret = PTR_ERR(parent_clk);
+ clk_put(ctx->sclk_fimc_clk);
+ clk_put(ctx->fimc_clk);
+ clk_put(ctx->wb_clk);
+ clk_put(ctx->wb_b_clk);
+ goto err_ctx;
+ }
+
+ if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
+ dev_err(dev, "failed to set parent.\n");
+ clk_put(parent_clk);
+ clk_put(ctx->sclk_fimc_clk);
+ clk_put(ctx->fimc_clk);
+ clk_put(ctx->wb_clk);
+ clk_put(ctx->wb_b_clk);
+ goto err_ctx;
+ }
+ clk_put(parent_clk);
+ clk_set_rate(ctx->sclk_fimc_clk, FIMC_CLK_RATE);
+ clk_disable(ctx->sclk_fimc_clk);
+
+ /* resource memory */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "failed to find registers.\n");
+ ret = -ENOENT;
+ goto err_clk;
+ }
+
+ ctx->regs_res = request_mem_region(res->start, resource_size(res),
+ dev_name(dev));
+ if (!ctx->regs_res) {
+ dev_err(dev, "failed to claim register region.\n");
+ ret = -ENOENT;
+ goto err_clk;
+ }
+
+ ctx->regs = ioremap(res->start, resource_size(res));
+ if (!ctx->regs) {
+ dev_err(dev, "failed to map registers.\n");
+ ret = -ENXIO;
+ goto err_req_region;
+ }
+
+ /* resource irq */
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(dev, "failed to request irq resource.\n");
+ goto err_get_regs;
+ }
+
+ ctx->irq = res->start;
+ ret = request_threaded_irq(ctx->irq, NULL, fimc_irq_handler,
+ IRQF_ONESHOT, "drm_fimc", ctx);
+ if (ret < 0) {
+ dev_err(dev, "failed to request irq.\n");
+ goto err_get_regs;
+ }
+
+ /* context initailization */
+ ctx->ver = pdata->ver;
+ ctx->id = pdev->id;
+ ctx->capa = fimc_get_capability(ctx->ver);
+ if (!ctx->capa) {
+ dev_err(dev, "failed to get capability.\n");
+ goto err_get_irq;
+ }
+ ctx->pol = pdata->pol;
+
+#ifdef CONFIG_SLP_DISP_DEBUG
+ for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+ ret = device_create_file(&(pdev->dev),
+ &device_attrs[i]);
+ if (ret)
+ break;
+ }
+
+ if (ret < 0)
+ dev_err(&pdev->dev, "failed to add sysfs entries\n");
+#endif
+
+ DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+
+ ippdrv = &ctx->ippdrv;
+ ippdrv->dev = dev;
+ ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops;
+ ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops;
+ ippdrv->check_property = fimc_ippdrv_check_property;
+ ippdrv->reset = fimc_ippdrv_reset;
+ ippdrv->start = fimc_ippdrv_start;
+ ippdrv->stop = fimc_ippdrv_stop;
+
+ mutex_init(&ctx->lock);
+ platform_set_drvdata(pdev, ctx);
+
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ ret = exynos_drm_ippdrv_register(ippdrv);
+ if (ret < 0) {
+ dev_err(dev, "failed to register drm fimc device.\n");
+ goto err_get_irq;
+ }
+
+ dev_info(&pdev->dev, "drm fimc registered successfully.\n");
+
+ return 0;
+
+err_get_irq:
+ free_irq(ctx->irq, ctx);
+err_get_regs:
+ iounmap(ctx->regs);
+err_req_region:
+ release_resource(ctx->regs_res);
+ kfree(ctx->regs_res);
+err_clk:
+ clk_put(ctx->sclk_fimc_clk);
+ clk_put(ctx->fimc_clk);
+ clk_put(ctx->wb_clk);
+ clk_put(ctx->wb_b_clk);
+err_ctx:
+ kfree(ctx);
+ return ret;
+}
+
+static int __devexit fimc_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct fimc_context *ctx = get_fimc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+
+ exynos_drm_ippdrv_unregister(ippdrv);
+
+ pm_runtime_set_suspended(dev);
+ pm_runtime_disable(dev);
+
+ free_irq(ctx->irq, ctx);
+ iounmap(ctx->regs);
+ release_resource(ctx->regs_res);
+ kfree(ctx->regs_res);
+
+ clk_put(ctx->sclk_fimc_clk);
+ clk_put(ctx->fimc_clk);
+ clk_put(ctx->wb_clk);
+ clk_put(ctx->wb_b_clk);
+
+ kfree(ctx);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int fimc_suspend(struct device *dev)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+
+ DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+ if (pm_runtime_suspended(dev))
+ return 0;
+ /* ToDo */
+ return fimc_power_on(ctx, false);
+}
+
+static int fimc_resume(struct device *dev)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+
+ DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+ if (!pm_runtime_suspended(dev))
+ return fimc_power_on(ctx, true);
+ /* ToDo */
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int fimc_runtime_suspend(struct device *dev)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+
+ DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+ /* ToDo */
+ return fimc_power_on(ctx, false);
+}
+
+static int fimc_runtime_resume(struct device *dev)
+{
+ struct fimc_context *ctx = get_fimc_context(dev);
+
+ DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+ /* ToDo */
+ return fimc_power_on(ctx, true);
+}
+#endif
+
+static const struct dev_pm_ops fimc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
+ SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
+};
+
+/* ToDo: need to check use case platform_device_id */
+struct platform_driver fimc_driver = {
+ .probe = fimc_probe,
+ .remove = __devexit_p(fimc_remove),
+ .driver = {
+ .name = "exynos-drm-fimc",
+ .owner = THIS_MODULE,
+ .pm = &fimc_pm_ops,
+ },
+};
+
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_vidi.h b/drivers/gpu/drm/exynos/exynos_drm_fimc.h
index a4babe4..e631774 100644
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_vidi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.h
@@ -1,7 +1,8 @@
-/* exynos_drm_vidi.h
- *
+/*
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * Author: Inki Dae <inki.dae@samsung.com>
+ *
+ * Authors:
+ * Eunchul Kim <chulspro.kim@samsung.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -23,14 +24,10 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef _EXYNOS_DRM_VIDI_H_
-#define _EXYNOS_DRM_VIDI_H_
+#ifndef _EXYNOS_DRM_FIMC_H_
+#define _EXYNOS_DRM_FIMC_H_
+
+/* ToDo */
-#ifdef CONFIG_DRM_EXYNOS_VIDI
-int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file_priv);
-#else
-#define vidi_connection_ioctl NULL
-#endif
+#endif /* _EXYNOS_DRM_FIMC_H_ */
-#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
deleted file mode 100644
index 823bfb0..0000000
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ /dev/null
@@ -1,1543 +0,0 @@
-/* exynos_drm_fimd.c
- *
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Inki Dae <inki.dae@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-#include "drmP.h"
-#include "drm_backlight.h"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/pm_runtime.h>
-#include <linux/cma.h>
-
-#include <drm/exynos_drm.h>
-#include <plat/regs-fb-v4.h>
-
-#include <plat/fimd_lite_ext.h>
-
-#include <mach/map.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_fbdev.h"
-#include "exynos_drm_crtc.h"
-
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
-#include <linux/devfreq/exynos4_display.h>
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
-#include <plat/fimc.h>
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
-#include <plat/pd.h>
-#include <linux/pm_qos_params.h>
-#endif
-#define FIMD_GET_LCD_WIDTH _IOR('F', 302, int)
-#define FIMD_GET_LCD_HEIGHT _IOR('F', 303, int)
-#define FIMD_SET_WRITEBACK _IOW('F', 304, u32)
-#endif
-
-/*
- * FIMD is stand for Fully Interactive Mobile Display and
- * as a display controller, it transfers contents drawn on memory
- * to a LCD Panel through Display Interfaces such as RGB or
- * CPU Interface.
- */
-
-/* position control register for hardware window 0, 2 ~ 4.*/
-#define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16)
-#define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16)
-/* size control register for hardware window 0. */
-#define VIDOSD_C_SIZE_W0 (VIDOSD_BASE + 0x08)
-/* alpha control register for hardware window 1 ~ 4. */
-#define VIDOSD_C(win) (VIDOSD_BASE + 0x18 + (win) * 16)
-/* size control register for hardware window 1 ~ 4. */
-#define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16)
-
-#define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8)
-#define VIDWx_BUF_END(win, buf) (VIDW_BUF_END(buf) + (win) * 8)
-#define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4)
-
-/* color key control register for hardware window 1 ~ 4. */
-#define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + (x * 8))
-/* color key value register for hardware window 1 ~ 4. */
-#define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + (x * 8))
-
-/* FIMD has totally five hardware windows. */
-#define WINDOWS_NR 5
-
-#define get_fimd_context(dev) platform_get_drvdata(to_platform_device(dev))
-
-static struct s5p_fimd_ext_device *fimd_lite_dev, *mdnie;
-static struct s5p_fimd_dynamic_refresh *fimd_refresh;
-
-struct fimd_notifier_block {
- struct list_head list;
- void *data;
- int (*client_notifier)(unsigned int val, void *data);
-};
-
-static LIST_HEAD(fimd_notifier_list);
-static DEFINE_MUTEX(fimd_notifier_lock);
-
-struct fimd_win_data {
- unsigned int offset_x;
- unsigned int offset_y;
- unsigned int ovl_width;
- unsigned int ovl_height;
- unsigned int fb_width;
- unsigned int fb_height;
- unsigned int bpp;
- dma_addr_t dma_addr;
- void __iomem *vaddr;
- unsigned int buf_offsize;
- unsigned int line_size; /* bytes */
- bool enabled;
-};
-
-struct fimd_context {
- struct exynos_drm_subdrv subdrv;
- int irq;
- struct drm_crtc *crtc;
- struct clk *bus_clk;
- struct clk *lcd_clk;
- struct resource *regs_res;
- void __iomem *regs;
- struct fimd_win_data win_data[WINDOWS_NR];
- unsigned int clkdiv;
- unsigned int default_win;
- unsigned long irq_flags;
- u32 vidcon0;
- u32 vidcon1;
- bool suspended;
- struct mutex lock;
-
- struct exynos_drm_panel_info *panel;
- unsigned int high_freq;
- unsigned int dynamic_refresh;
- struct notifier_block nb_exynos_display;
-
- struct work_struct work;
- bool errata;
-#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
- struct notifier_block nb_ctrl;
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- struct pm_qos_request_list pm_qos;
-#endif
-#endif
-};
-
-static bool fimd_display_is_connected(struct device *dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO. */
-
- return true;
-}
-
-static void *fimd_get_panel(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return ctx->panel;
-}
-
-static int fimd_check_timing(struct device *dev, void *timing)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO. */
-
- return 0;
-}
-
-static int fimd_display_power_on(struct device *dev, int mode)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO */
-
- drm_bl_dpms(mode);
-
- return 0;
-}
-
-static struct exynos_drm_display_ops fimd_display_ops = {
- .type = EXYNOS_DISPLAY_TYPE_LCD,
- .is_connected = fimd_display_is_connected,
- .get_panel = fimd_get_panel,
- .check_timing = fimd_check_timing,
- .power_on = fimd_display_power_on,
-};
-
-static void exynos_drm_mdnie_mode_stop(struct fimd_context *ctx)
-{
- struct s5p_fimd_ext_driver *fimd_lite_drv;
- u32 cfg;
-
- fimd_lite_drv = to_fimd_ext_driver(fimd_lite_dev->dev.driver);
-
- /* set dualrgb register to mDNIe mode. */
- cfg = readl(ctx->regs + DUALRGB);
- cfg &= ~(0x3 << 0);
- writel(cfg, ctx->regs + DUALRGB);
- msleep(20);
-
- /* change display path. */
- cfg = readl(S3C_VA_SYS + 0x210);
- cfg |= 1 << 1;
- writel(cfg, S3C_VA_SYS + 0x210);
-
- if (fimd_lite_drv->stop)
- fimd_lite_drv->stop(fimd_lite_dev);
-
- if (fimd_lite_drv->setup)
- fimd_lite_drv->setup(fimd_lite_dev, 0);
-
- /* clock off */
- if (fimd_lite_drv->power_off)
- fimd_lite_drv->power_off(fimd_lite_dev);
-
- fimd_lite_dev->enabled = false;
-}
-
-static void exynos_drm_set_mdnie_mode(struct fimd_context *ctx)
-{
- u32 cfg;
-
- /* change display path. */
- cfg = readl(S3C_VA_SYS + 0x210);
- /* MIE_LBLK0 is mDNIe. */
- cfg |= 1 << 0;
- /* FIMDBYPASS_LBLK0 is MIE/mDNIe. */
- cfg &= ~(1 << 1);
- writel(cfg, S3C_VA_SYS + 0x210);
-
- /* all polarity values should be 0 for mDNIe. */
- cfg = readl(ctx->regs + VIDCON1);
- cfg &= ~(VIDCON1_INV_VCLK | VIDCON1_INV_HSYNC |
- VIDCON1_INV_VSYNC | VIDCON1_INV_VDEN |
- VIDCON1_VCLK_MASK);
-
- writel(cfg, ctx->regs + VIDCON1);
-
- /* set dualrgb register to mDNIe mode. */
- cfg = readl(ctx->regs + DUALRGB);
- cfg &= ~(0x3 << 0);
- cfg |= 0x3 << 0;
- writel(cfg, ctx->regs + DUALRGB);
-}
-
-static int exynos_drm_change_to_mdnie(struct fimd_context *ctx)
-{
- u32 cfg;
- struct s5p_fimd_ext_driver *mdnie_drv, *fimd_lite_drv;
-
- mdnie_drv = to_fimd_ext_driver(mdnie->dev.driver);
- fimd_lite_drv = to_fimd_ext_driver(fimd_lite_dev->dev.driver);
-
- /**
- * path change sequence for mDNIe.
- *
- * 1. FIMD-LITE DMA stop.
- * 2. FIMD DMA stop.
- * 3. change DISPLAY_CONTROL and DUALRGB registers to mDNIe mode.
- * 4. change FIMD VCLKFREE to freerun mode.
- * 5. initialize mDNIe module.
- * 6. initialize FIMD-LITE module.
- * 7. FIMD-LITE logic start.
- * 8. FIMD-LITE DMA start.
- * 9. FIMD DMA start.
- *
- * ps. FIMD polarity values should be 0.
- * lcd polarity values should be set to FIMD-LITE.
- * FIMD and FIMD-LITE DMA should be started at same time.
- */
- /* set fimd to mDNIe mode.(WB/mDNIe) */
- exynos_drm_set_mdnie_mode(ctx);
-
- /* enable FIMD-LITE. clk */
- if (fimd_lite_drv && fimd_lite_drv->power_on)
- fimd_lite_drv->power_on(fimd_lite_dev);
-
- /* setup mDNIe. */
- if (mdnie_drv)
- mdnie_drv->setup(mdnie, 1);
-
- /* setup FIMD-LITE. */
- if (fimd_lite_drv)
- fimd_lite_drv->setup(fimd_lite_dev, 1);
-
- cfg = readl(ctx->regs + VIDCON0);
- cfg |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- writel(cfg, ctx->regs + VIDCON0);
-
- if (fimd_lite_drv->start)
- fimd_lite_drv->start(fimd_lite_dev);
- return 0;
-}
-
-static void fimd_dpms(struct device *subdrv_dev, int mode)
-{
- struct fimd_context *ctx = get_fimd_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
-
- mutex_lock(&ctx->lock);
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- /*
- * enable fimd hardware only if suspended status.
- *
- * P.S. fimd_dpms function would be called at booting time so
- * clk_enable could be called double time.
- */
- if (ctx->suspended)
- pm_runtime_get_sync(subdrv_dev);
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- if (!ctx->suspended)
- pm_runtime_put_sync(subdrv_dev);
- break;
- default:
- DRM_DEBUG_KMS("unspecified mode %d\n", mode);
- break;
- }
-
- mutex_unlock(&ctx->lock);
-}
-
-static void fimd_apply(struct device *subdrv_dev)
-{
- struct fimd_context *ctx = get_fimd_context(subdrv_dev);
- struct exynos_drm_manager *mgr = ctx->subdrv.manager;
- struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
- struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
- struct fimd_win_data *win_data;
- int i;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- for (i = 0; i < WINDOWS_NR; i++) {
- win_data = &ctx->win_data[i];
- if (win_data->enabled && (ovl_ops && ovl_ops->commit))
- ovl_ops->commit(subdrv_dev, i);
- }
-
- if (mgr_ops && mgr_ops->commit)
- mgr_ops->commit(subdrv_dev);
-}
-
-static void fimd_commit(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
- u32 val;
-
- if (ctx->suspended)
- return;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* setup polarity values from machine code. */
- writel(ctx->vidcon1, ctx->regs + VIDCON1);
-
- /* setup vertical timing values. */
- val = VIDTCON0_VBPD(timing->upper_margin - 1) |
- VIDTCON0_VFPD(timing->lower_margin - 1) |
- VIDTCON0_VSPW(timing->vsync_len - 1);
- writel(val, ctx->regs + VIDTCON0);
-
- /* setup horizontal timing values. */
- val = VIDTCON1_HBPD(timing->left_margin - 1) |
- VIDTCON1_HFPD(timing->right_margin - 1) |
- VIDTCON1_HSPW(timing->hsync_len - 1);
- writel(val, ctx->regs + VIDTCON1);
-
- /* setup horizontal and vertical display size. */
- val = VIDTCON2_LINEVAL(timing->yres - 1) |
- VIDTCON2_HOZVAL(timing->xres - 1);
- writel(val, ctx->regs + VIDTCON2);
-
- /* setup clock source, clock divider, enable dma. */
- val = ctx->vidcon0;
- val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
-
- if (ctx->clkdiv > 1)
- val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
- else
- val &= ~VIDCON0_CLKDIR; /* 1:1 clock */
-
- /*
- * fields of register with prefix '_F' would be updated
- * at vsync(same as dma start)
- */
- val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- writel(val, ctx->regs + VIDCON0);
-
- /*
- * fix fimd errata with mDNIe.
- *
- * this code fixes a issue that mDNIe unfunctions properly
- * when fimd power off goes to on. this issue is because dma
- * is enabled two times with setcrtc call once a process is
- * ternimated(at this thime, fimd goes to on from off for back
- * to console fb) so this condition would avoid the situation.
- */
- if (!ctx->errata) {
- /*
- * Workaround: After power domain is turned off then
- * when it is turned on, this needs.
- */
- val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F);
- writel(val, ctx->regs + VIDCON0);
-
- val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- writel(val, ctx->regs + VIDCON0);
-
- ctx->errata = true;
- }
-}
-
-static int fimd_enable_vblank(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- u32 val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return -EPERM;
-
- if (!test_and_set_bit(0, &ctx->irq_flags)) {
- val = readl(ctx->regs + VIDINTCON0);
-
- val |= VIDINTCON0_INT_ENABLE;
- val |= VIDINTCON0_INT_FRAME;
-
- val &= ~VIDINTCON0_FRAMESEL0_MASK;
- val |= VIDINTCON0_FRAMESEL0_VSYNC;
- val &= ~VIDINTCON0_FRAMESEL1_MASK;
- val |= VIDINTCON0_FRAMESEL1_NONE;
-
- writel(val, ctx->regs + VIDINTCON0);
- }
-
- return 0;
-}
-
-static void fimd_disable_vblank(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- u32 val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return;
-
- if (test_and_clear_bit(0, &ctx->irq_flags)) {
- val = readl(ctx->regs + VIDINTCON0);
-
- val &= ~VIDINTCON0_INT_FRAME;
- val &= ~VIDINTCON0_INT_ENABLE;
-
- writel(val, ctx->regs + VIDINTCON0);
- }
-}
-
-static struct exynos_drm_manager_ops fimd_manager_ops = {
- .dpms = fimd_dpms,
- .apply = fimd_apply,
- .commit = fimd_commit,
- .enable_vblank = fimd_enable_vblank,
- .disable_vblank = fimd_disable_vblank,
-};
-
-static void fimd_win_mode_set(struct device *dev,
- struct exynos_drm_overlay *overlay)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct fimd_win_data *win_data;
- int win;
- unsigned long offset;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!overlay) {
- dev_err(dev, "overlay is NULL\n");
- return;
- }
-
- win = overlay->zpos;
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- offset = overlay->fb_x * (overlay->bpp >> 3);
- offset += overlay->fb_y * overlay->pitch;
-
- DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
-
- win_data = &ctx->win_data[win];
-
- win_data->offset_x = overlay->crtc_x;
- win_data->offset_y = overlay->crtc_y;
- win_data->ovl_width = overlay->crtc_width;
- win_data->ovl_height = overlay->crtc_height;
- win_data->fb_width = overlay->fb_width;
- win_data->fb_height = overlay->fb_height;
- win_data->dma_addr = overlay->dma_addr[0] + offset;
- win_data->vaddr = overlay->vaddr[0] + offset;
- win_data->bpp = overlay->bpp;
- win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
- (overlay->bpp >> 3);
- win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
-
- DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
- win_data->offset_x, win_data->offset_y);
- DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
- win_data->ovl_width, win_data->ovl_height);
- DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
- (unsigned long)win_data->dma_addr,
- (unsigned long)win_data->vaddr);
- DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
- overlay->fb_width, overlay->crtc_width);
-}
-
-static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct fimd_win_data *win_data = &ctx->win_data[win];
- unsigned long val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- val = WINCONx_ENWIN;
-
- switch (win_data->bpp) {
- case 1:
- val |= WINCON0_BPPMODE_1BPP;
- val |= WINCONx_BITSWP;
- val |= WINCONx_BURSTLEN_4WORD;
- break;
- case 2:
- val |= WINCON0_BPPMODE_2BPP;
- val |= WINCONx_BITSWP;
- val |= WINCONx_BURSTLEN_8WORD;
- break;
- case 4:
- val |= WINCON0_BPPMODE_4BPP;
- val |= WINCONx_BITSWP;
- val |= WINCONx_BURSTLEN_8WORD;
- break;
- case 8:
- val |= WINCON0_BPPMODE_8BPP_PALETTE;
- val |= WINCONx_BURSTLEN_8WORD;
- val |= WINCONx_BYTSWP;
- break;
- case 16:
- val |= WINCON0_BPPMODE_16BPP_565;
- val |= WINCONx_HAWSWP;
- val |= WINCONx_BURSTLEN_16WORD;
- break;
- case 24:
- val |= WINCON0_BPPMODE_24BPP_888;
- val |= WINCONx_WSWP;
- val |= WINCONx_BURSTLEN_16WORD;
- break;
- case 32:
- val |= WINCON1_BPPMODE_28BPP_A4888
- | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
- val |= WINCONx_WSWP;
- val |= WINCONx_BURSTLEN_16WORD;
- break;
- default:
- DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
-
- val |= WINCON0_BPPMODE_24BPP_888;
- val |= WINCONx_WSWP;
- val |= WINCONx_BURSTLEN_16WORD;
- break;
- }
-
- DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
-
- writel(val, ctx->regs + WINCON(win));
-}
-
-static void fimd_win_set_colkey(struct device *dev, unsigned int win)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- unsigned int keycon0 = 0, keycon1 = 0;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
- WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
-
- keycon1 = WxKEYCON1_COLVAL(0xffffffff);
-
- writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
- writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
-}
-
-static void fimd_win_commit(struct device *dev, int zpos)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct fimd_win_data *win_data;
- int win = zpos;
- unsigned long val, alpha, size;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return;
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- win_data = &ctx->win_data[win];
-
- /*
- * SHADOWCON register is used for enabling timing.
- *
- * for example, once only width value of a register is set,
- * if the dma is started then fimd hardware could malfunction so
- * with protect window setting, the register fields with prefix '_F'
- * wouldn't be updated at vsync also but updated once unprotect window
- * is set.
- */
-
- /* protect windows */
- val = readl(ctx->regs + SHADOWCON);
- val |= SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-
- /* buffer start address */
- val = (unsigned long)win_data->dma_addr;
- writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
-
- /* buffer end address */
- size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
- val = (unsigned long)(win_data->dma_addr + size);
- writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
-
- DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
- (unsigned long)win_data->dma_addr, val, size);
- DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
- win_data->ovl_width, win_data->ovl_height);
-
- /* buffer size */
- val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
- VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size);
- writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
-
- /* OSD position */
- val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
- VIDOSDxA_TOPLEFT_Y(win_data->offset_y);
- writel(val, ctx->regs + VIDOSD_A(win));
-
- val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x +
- win_data->ovl_width - 1) |
- VIDOSDxB_BOTRIGHT_Y(win_data->offset_y +
- win_data->ovl_height - 1);
- writel(val, ctx->regs + VIDOSD_B(win));
-
- DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
- win_data->offset_x, win_data->offset_y,
- win_data->offset_x + win_data->ovl_width - 1,
- win_data->offset_y + win_data->ovl_height - 1);
-
- /* hardware window 0 doesn't support alpha channel. */
- if (win != 0) {
- /* OSD alpha */
- alpha = VIDISD14C_ALPHA1_R(0xf) |
- VIDISD14C_ALPHA1_G(0xf) |
- VIDISD14C_ALPHA1_B(0xf);
-
- writel(alpha, ctx->regs + VIDOSD_C(win));
- }
-
- /* OSD size */
- if (win != 3 && win != 4) {
- u32 offset = VIDOSD_D(win);
- if (win == 0)
- offset = VIDOSD_C_SIZE_W0;
- val = win_data->ovl_width * win_data->ovl_height;
- writel(val, ctx->regs + offset);
-
- DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
- }
-
- fimd_win_set_pixfmt(dev, win);
-
- /* hardware window 0 doesn't support color key. */
- if (win != 0)
- fimd_win_set_colkey(dev, win);
-
- /* wincon */
- val = readl(ctx->regs + WINCON(win));
- val |= WINCONx_ENWIN;
- writel(val, ctx->regs + WINCON(win));
-
- /* Enable DMA channel and unprotect windows */
- val = readl(ctx->regs + SHADOWCON);
- val |= SHADOWCON_CHx_ENABLE(win);
- val &= ~SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-
- win_data->enabled = true;
-}
-
-static void fimd_win_disable(struct device *dev, int zpos)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct fimd_win_data *win_data;
- int win = zpos;
- u32 val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- win_data = &ctx->win_data[win];
-
- /* protect windows */
- val = readl(ctx->regs + SHADOWCON);
- val |= SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-
- /* wincon */
- val = readl(ctx->regs + WINCON(win));
- val &= ~WINCONx_ENWIN;
- writel(val, ctx->regs + WINCON(win));
-
- /* unprotect windows */
- val = readl(ctx->regs + SHADOWCON);
- val &= ~SHADOWCON_CHx_ENABLE(win);
- val &= ~SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-
- win_data->enabled = false;
-}
-
-static struct exynos_drm_overlay_ops fimd_overlay_ops = {
- .mode_set = fimd_win_mode_set,
- .commit = fimd_win_commit,
- .disable = fimd_win_disable,
-};
-
-static struct exynos_drm_manager fimd_manager = {
- .pipe = -1,
- .ops = &fimd_manager_ops,
- .overlay_ops = &fimd_overlay_ops,
- .display_ops = &fimd_display_ops,
-};
-
-static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
-{
- struct exynos_drm_private *dev_priv = drm_dev->dev_private;
- struct drm_pending_vblank_event *e, *t;
- struct timeval now;
- unsigned long flags;
- bool is_checked = false;
-
- spin_lock_irqsave(&drm_dev->event_lock, flags);
-
- list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
- base.link) {
- /* if event's pipe isn't same as crtc then ignore it. */
- if (crtc != e->pipe)
- continue;
-
- is_checked = true;
-
- do_gettimeofday(&now);
- e->event.sequence = 0;
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
-
- list_move_tail(&e->base.link, &e->base.file_priv->event_list);
- wake_up_interruptible(&e->base.file_priv->event_wait);
- }
-
- if (is_checked) {
- /*
- * call drm_vblank_put only in case that drm_vblank_get was
- * called.
- */
- if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
- drm_vblank_put(drm_dev, crtc);
-
- /*
- * don't off vblank if vblank_disable_allowed is 1,
- * because vblank would be off by timer handler.
- */
- if (!drm_dev->vblank_disable_allowed)
- drm_vblank_off(drm_dev, crtc);
- }
-
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-}
-
-static void exynos_fimd_schedule_work(struct work_struct *work)
-{
- struct fimd_context *ctx = container_of(work, struct fimd_context,
- work);
- u32 ret;
-
- /* Change mdnie mode after irq handler */
- if (mdnie && fimd_lite_dev) {
- if (!fimd_lite_dev->enabled) {
- while (1) {
- ret = (__raw_readl(ctx->regs + VIDCON1)) &
- VIDCON1_VSTATUS_MASK;
- if (ret == VIDCON1_VSTATUS_BACKPORCH) {
- exynos_drm_change_to_mdnie(ctx);
- fimd_lite_dev->enabled = true;
- break;
- }
- }
- }
- }
-
-}
-
-static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
-{
- struct fimd_context *ctx = (struct fimd_context *)dev_id;
- struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct drm_device *drm_dev = subdrv->drm_dev;
- struct exynos_drm_manager *manager = subdrv->manager;
- u32 val;
-
- val = readl(ctx->regs + VIDINTCON1);
-
- if (val & VIDINTCON1_INT_FRAME)
- /* VSYNC interrupt */
- writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
-
- /* check the crtc is detached already from encoder */
- if (manager->pipe < 0)
- goto out;
-
- drm_handle_vblank(drm_dev, manager->pipe);
- fimd_finish_pageflip(drm_dev, manager->pipe);
-
- schedule_work(&ctx->work);
-
-out:
- return IRQ_HANDLED;
-}
-
-static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * enable drm irq mode.
- * - with irq_enabled = 1, we can use the vblank feature.
- *
- * P.S. note that we wouldn't use drm irq handler but
- * just specific driver own one instead because
- * drm framework supports only one irq handler.
- */
- drm_dev->irq_enabled = 1;
-
- /*
- * with vblank_disable_allowed = 1, vblank interrupt will be disabled
- * by drm timer once a current process gives up ownership of
- * vblank event.(after drm_vblank_put function is called)
- */
- drm_dev->vblank_disable_allowed = 1;
-
- return 0;
-}
-
-static void fimd_subdrv_remove(struct drm_device *drm_dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO. */
-}
-
-static int fimd_calc_clkdiv(struct fimd_context *ctx,
- struct fb_videomode *timing)
-{
- unsigned long clk = clk_get_rate(ctx->lcd_clk);
- u32 retrace;
- u32 clkdiv;
- u32 best_framerate = 0;
- u32 framerate;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- retrace = timing->left_margin + timing->hsync_len +
- timing->right_margin + timing->xres;
- retrace *= timing->upper_margin + timing->vsync_len +
- timing->lower_margin + timing->yres;
-
- /* default framerate is 60Hz */
- if (!timing->refresh)
- timing->refresh = 60;
-
- clk /= retrace;
-
- for (clkdiv = 1; clkdiv < 0x100; clkdiv++) {
- int tmp;
-
- /* get best framerate */
- framerate = clk / clkdiv;
- tmp = timing->refresh - framerate;
- if (tmp < 0) {
- best_framerate = framerate;
- continue;
- } else {
- if (!best_framerate)
- best_framerate = framerate;
- else if (tmp < (best_framerate - framerate))
- best_framerate = framerate;
- break;
- }
- }
-
- return clkdiv;
-}
-
-static void fimd_clear_win(struct fimd_context *ctx, int win)
-{
- u32 val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- writel(0, ctx->regs + WINCON(win));
- writel(0, ctx->regs + VIDOSD_A(win));
- writel(0, ctx->regs + VIDOSD_B(win));
- writel(0, ctx->regs + VIDOSD_C(win));
-
- if (win == 1 || win == 2)
- writel(0, ctx->regs + VIDOSD_D(win));
-
- val = readl(ctx->regs + SHADOWCON);
- val &= ~SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-}
-
-int fimd_register_client(int (*client_notifier)(unsigned int val, void *data),
- void *data)
-{
- struct fimd_notifier_block *fimd_block;
-
- fimd_block = kzalloc(sizeof(*fimd_block), GFP_KERNEL);
- if (!fimd_block) {
- printk(KERN_ERR "failed to allocate fimd_notifier_block\n");
- return -ENOMEM;
- }
-
- fimd_block->client_notifier = client_notifier;
- fimd_block->data = data;
-
- mutex_lock(&fimd_notifier_lock);
- list_add_tail(&fimd_block->list, &fimd_notifier_list);
- mutex_unlock(&fimd_notifier_lock);
-
- return 0;
-}
-EXPORT_SYMBOL(fimd_register_client);
-
-void fimd_unregister_client(int (*client_notifier)(unsigned int val,
- void *data))
-{
- struct fimd_notifier_block *fimd_block;
-
- mutex_lock(&fimd_notifier_lock);
- list_for_each_entry(fimd_block, &fimd_notifier_list, list) {
- if (!fimd_block)
- continue;
-
- if (fimd_block->client_notifier == client_notifier) {
- list_del(&fimd_block->list);
- kfree(fimd_block);
- fimd_block = NULL;
- break;
- }
- }
- mutex_unlock(&fimd_notifier_lock);
-}
-EXPORT_SYMBOL(fimd_unregister_client);
-
-static int fimd_notifier_call_chain(void)
-{
- struct fimd_notifier_block *fimd_block;
-
- mutex_lock(&fimd_notifier_lock);
- list_for_each_entry(fimd_block, &fimd_notifier_list, list) {
- if (fimd_block && fimd_block->client_notifier)
- fimd_block->client_notifier(0, fimd_block->data);
- }
- mutex_unlock(&fimd_notifier_lock);
-
- return 0;
-}
-
-static int fimd_power_on(struct fimd_context *ctx, bool enable)
-{
- struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct device *dev = subdrv->dev;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (enable != false && enable != true)
- return -EINVAL;
-
- if (enable) {
- int ret;
-
- /* fimd power should be off to clear mipi-dsi fifo. */
- fimd_notifier_call_chain();
-
- ret = clk_enable(ctx->bus_clk);
- if (ret < 0)
- return ret;
-
- ret = clk_enable(ctx->lcd_clk);
- if (ret < 0) {
- clk_disable(ctx->bus_clk);
- return ret;
- }
-
- ctx->suspended = false;
-
- /* if vblank was enabled status, enable it again. */
- if (test_and_clear_bit(0, &ctx->irq_flags))
- fimd_enable_vblank(dev);
-
- fimd_apply(dev);
- } else {
- if (fimd_lite_dev)
- exynos_drm_mdnie_mode_stop(ctx);
-
- clk_disable(ctx->lcd_clk);
- clk_disable(ctx->bus_clk);
-
- ctx->suspended = true;
- ctx->errata = false;
- }
-
- return 0;
-}
-
-static void exynos_drm_change_clock(struct fimd_context *ctx)
-{
- unsigned int cfg = 0;
- struct s5p_fimd_ext_driver *fimd_lite_drv;
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
-
- fimd_lite_drv = to_fimd_ext_driver(fimd_lite_dev->dev.driver);
-
- if (!ctx->dynamic_refresh) {
- timing->refresh = 60;
- ctx->clkdiv = fimd_calc_clkdiv(ctx, timing);
-#ifdef CONFIG_LCD_S6E8AA0
- /* workaround: To apply dynamic refresh rate */
- s6e8aa0_panel_cond(1);
-#endif
- if (fimd_lite_dev && fimd_lite_dev->enabled) {
- fimd_refresh->clkdiv = ctx->clkdiv;
- fimd_lite_drv->change_clock(fimd_refresh,
- fimd_lite_dev);
- } else {
- cfg = readl(ctx->regs + VIDCON0);
- cfg &= ~VIDCON0_CLKVAL_F(0xFF);
- cfg |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1);
- writel(cfg, ctx->regs + VIDCON0);
- }
- } else {
- ctx->clkdiv = fimd_calc_clkdiv(ctx, timing);
-#ifdef CONFIG_LCD_S6E8AA0
- /* workaround: To apply dynamic refresh rate */
- s6e8aa0_panel_cond(ctx->high_freq);
-#endif
- if (fimd_lite_dev && fimd_lite_dev->enabled) {
- fimd_refresh->clkdiv = ctx->clkdiv;
- fimd_lite_drv->change_clock(fimd_refresh,
- fimd_lite_dev);
- } else {
- cfg = readl(ctx->regs + VIDCON0);
- cfg &= ~VIDCON0_CLKVAL_F(0xFF);
- cfg |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1);
- writel(cfg, ctx->regs + VIDCON0);
- }
- }
-}
-
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
-static int exynos_display_notifier_callback(struct notifier_block *this,
- unsigned long event, void *_data)
-{
- struct fimd_context *ctx
- = container_of(this, struct fimd_context, nb_exynos_display);
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
-
- if (ctx->suspended)
- return NOTIFY_DONE;
-
- switch (event) {
- case EXYNOS4_DISPLAY_LV_HF:
- timing->refresh = EXYNOS4_DISPLAY_LV_HF;
- ctx->high_freq = 1;
- break;
- case EXYNOS4_DISPLAY_LV_LF:
- timing->refresh = EXYNOS4_DISPLAY_LV_LF;
- ctx->high_freq = 0;
- break;
- default:
- return NOTIFY_BAD;
- }
-
- exynos_drm_change_clock(ctx);
-
- return NOTIFY_DONE;
-}
-#endif
-
-static ssize_t store_refresh(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
- unsigned long refresh;
- int ret;
-
- if (ctx->dynamic_refresh) {
- ret = kstrtoul(buf, 0, &refresh);
- timing->refresh = refresh;
- if (refresh == 60)
- ctx->high_freq = 1;
- else
- ctx->high_freq = 0;
-
- exynos_drm_change_clock(ctx);
- }
-
- return count;
-}
-
-static ssize_t show_refresh(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", timing->refresh);
-}
-
-static struct device_attribute device_attrs[] = {
- __ATTR(refresh, S_IRUGO|S_IWUSR, show_refresh, store_refresh),
-};
-
-#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
-static void fimd_set_writeback(struct fimd_context *ctx, int enable)
-{
- u32 vidcon0 = readl(ctx->regs + VIDCON0);
- u32 vidcon2 = readl(ctx->regs + VIDCON2);
-
- vidcon0 &= ~VIDCON0_VIDOUT_MASK;
- vidcon2 &= ~(VIDCON2_WB_MASK |
- VIDCON2_WB_SKIP_MASK |
- VIDCON2_TVFORMATSEL_HW_SW_MASK |
- VIDCON2_TVFORMATSEL_MASK);
-
- if (enable) {
- vidcon0 |= VIDCON0_VIDOUT_WB;
- vidcon2 |= (VIDCON2_WB_ENABLE |
- VIDCON2_TVFORMATSEL_SW |
- VIDCON2_TVFORMATSEL_YUV444);
- } else {
- vidcon0 |= VIDCON0_VIDOUT_RGB;
- vidcon2 |= VIDCON2_WB_DISABLE;
- }
-
- writel(vidcon0, ctx->regs + VIDCON0);
- writel(vidcon2, ctx->regs + VIDCON2);
-}
-
-static int fimd_notifier_ctrl(struct notifier_block *this,
- unsigned long event, void *_data)
-{
- struct fimd_context *ctx = container_of(this,
- struct fimd_context, nb_ctrl);
-
- switch (event) {
- case FIMD_GET_LCD_WIDTH: {
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
- int *width = (int *)_data;
-
- *width = timing->xres;
- }
- break;
- case FIMD_GET_LCD_HEIGHT: {
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
- int *height = (int *)_data;
-
- *height = timing->yres;
- }
- break;
- case FIMD_SET_WRITEBACK: {
- unsigned int refresh;
- int *enable = (int *)&_data;
-
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- if (*enable)
- refresh = EXYNOS4_DISPLAY_LV_HF;
- else
- refresh = EXYNOS4_DISPLAY_LV_LF;
- pm_qos_update_request(&ctx->pm_qos,
- refresh);
-#endif
- fimd_set_writeback(ctx, *enable);
- }
- break;
- default:
- /* ToDo : for checking use case */
- DRM_INFO("%s:event[0x%x]\n", __func__, (unsigned int)event);
- break;
- }
-
- return NOTIFY_DONE;
-}
-#endif
-
-static int __devinit fimd_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct fimd_context *ctx;
- struct exynos_drm_subdrv *subdrv;
- struct exynos_drm_fimd_pdata *pdata;
- struct exynos_drm_panel_info *panel;
- struct resource *res;
- int win;
- int i;
- int ret = -EINVAL;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(dev, "no platform data specified\n");
- return -EINVAL;
- }
-
- panel = &pdata->panel;
- if (!panel) {
- dev_err(dev, "panel is null.\n");
- return -EINVAL;
- }
-
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
-
- ctx->bus_clk = clk_get(dev, "lcd");
- if (IS_ERR(ctx->bus_clk)) {
- dev_err(dev, "failed to get bus clock\n");
- ret = PTR_ERR(ctx->bus_clk);
- goto err_clk_get;
- }
-
- clk_enable(ctx->bus_clk);
-
- ctx->lcd_clk = clk_get(dev, "sclk_fimd");
- if (IS_ERR(ctx->lcd_clk)) {
- dev_err(dev, "failed to get lcd clock\n");
- ret = PTR_ERR(ctx->lcd_clk);
- goto err_bus_clk;
- }
-
- clk_enable(ctx->lcd_clk);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "failed to find registers\n");
- ret = -ENOENT;
- goto err_clk;
- }
-
- ctx->regs_res = request_mem_region(res->start, resource_size(res),
- dev_name(dev));
- if (!ctx->regs_res) {
- dev_err(dev, "failed to claim register region\n");
- ret = -ENOENT;
- goto err_clk;
- }
-
- ctx->regs = ioremap(res->start, resource_size(res));
- if (!ctx->regs) {
- dev_err(dev, "failed to map registers\n");
- ret = -ENXIO;
- goto err_req_region_io;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(dev, "irq request failed.\n");
- goto err_get_resource;
- }
-
- ctx->irq = res->start;
-
- ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx);
- if (ret < 0) {
- dev_err(dev, "irq request failed.\n");
- goto err_get_resource;
- }
-
- ctx->clkdiv = fimd_calc_clkdiv(ctx, &panel->timing);
- ctx->vidcon0 = pdata->vidcon0;
- ctx->vidcon1 = pdata->vidcon1;
- ctx->default_win = pdata->default_win;
- ctx->dynamic_refresh = pdata->dynamic_refresh;
- ctx->panel = panel;
-
- INIT_WORK(&ctx->work, exynos_fimd_schedule_work);
-
- panel->timing.pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv;
-
- DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n",
- panel->timing.pixclock, ctx->clkdiv);
-
- /* mdnie support. */
- mdnie = s5p_fimd_ext_find_device("mdnie");
- fimd_lite_dev = s5p_fimd_ext_find_device("fimd_lite");
- if (mdnie && fimd_lite_dev) {
- fimd_refresh = kzalloc(sizeof(*fimd_refresh), GFP_KERNEL);
- if (!fimd_refresh) {
- dev_err(dev, "failed to allocate fimd_refresh.\n");
- ret = -ENOMEM;
- goto err_alloc_fail;
- }
-
- fimd_refresh->dynamic_refresh = pdata->dynamic_refresh;
- fimd_refresh->regs = ctx->regs;
- fimd_refresh->clkdiv = ctx->clkdiv;
- }
-
- for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
- ret = device_create_file(&(pdev->dev),
- &device_attrs[i]);
- if (ret)
- break;
- }
-
- if (ret < 0)
- dev_err(&pdev->dev, "failed to add sysfs entries\n");
-
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- ctx->nb_exynos_display.notifier_call = exynos_display_notifier_callback;
- ret = exynos4_display_register_client(&ctx->nb_exynos_display);
- if (ret < 0)
- dev_warn(dev, "failed to register exynos-display notifier\n");
-#endif
-
- dev_info(&pdev->dev, "registered successfully\n");
-
- subdrv = &ctx->subdrv;
-
- subdrv->dev = dev;
- subdrv->manager = &fimd_manager;
- subdrv->probe = fimd_subdrv_probe;
- subdrv->remove = fimd_subdrv_remove;
-
-#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
- ctx->nb_ctrl.notifier_call = fimd_notifier_ctrl;
- ret = fimc_register_client(&ctx->nb_ctrl);
- if (ret) {
- dev_err(dev, "could not register fimd notify callback\n");
- goto err_alloc_fail;
- }
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- pm_qos_add_request(&ctx->pm_qos,
- PM_QOS_DISPLAY_FREQUENCY, EXYNOS4_DISPLAY_LV_LF);
-#endif
-#endif
-
- mutex_init(&ctx->lock);
-
- platform_set_drvdata(pdev, ctx);
-
- pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
- pm_runtime_get_sync(dev);
-
- for (win = 0; win < WINDOWS_NR; win++)
- if (win != ctx->default_win)
- fimd_clear_win(ctx, win);
-
- exynos_drm_subdrv_register(subdrv);
-
- return 0;
-
-err_alloc_fail:
- free_irq(ctx->irq, ctx);
-
-err_get_resource:
- iounmap(ctx->regs);
-
-err_req_region_io:
- release_resource(ctx->regs_res);
- kfree(ctx->regs_res);
-
-err_clk:
- clk_disable(ctx->lcd_clk);
- clk_put(ctx->lcd_clk);
-
-err_bus_clk:
- clk_disable(ctx->bus_clk);
- clk_put(ctx->bus_clk);
-
-err_clk_get:
- kfree(ctx);
- return ret;
-}
-
-static int __devexit fimd_remove(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct fimd_context *ctx = platform_get_drvdata(pdev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_drm_subdrv_unregister(&ctx->subdrv);
-#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
- fimc_unregister_client(&ctx->nb_ctrl);
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- pm_qos_remove_request(&ctx->pm_qos);
-#endif
-#endif
-
- if (ctx->suspended)
- goto out;
-
- pm_runtime_set_suspended(dev);
- pm_runtime_put_sync(dev);
-
-out:
- pm_runtime_disable(dev);
-
- clk_put(ctx->lcd_clk);
- clk_put(ctx->bus_clk);
-
-
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- exynos4_display_unregister_client(&ctx->nb_exynos_display);
-#endif
-
- iounmap(ctx->regs);
- release_resource(ctx->regs_res);
- kfree(ctx->regs_res);
- free_irq(ctx->irq, ctx);
-
- kfree(ctx);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int fimd_suspend(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
-
- if (pm_runtime_suspended(dev))
- return 0;
-
- /*
- * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
- * called here, an error would be returned by that interface
- * because the usage_count of pm runtime is more than 1.
- */
- return fimd_power_on(ctx, false);
-}
-
-static int fimd_resume(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
-
- /*
- * if entered to sleep when lcd panel was on, the usage_count
- * of pm runtime would still be 1 so in this case, fimd driver
- * should be on directly not drawing on pm runtime interface.
- */
- if (!pm_runtime_suspended(dev))
- return fimd_power_on(ctx, true);
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int fimd_runtime_suspend(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return fimd_power_on(ctx, false);
-}
-
-static int fimd_runtime_resume(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return fimd_power_on(ctx, true);
-}
-#endif
-
-static const struct dev_pm_ops fimd_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
- SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
-};
-
-struct platform_driver fimd_driver = {
- .probe = fimd_probe,
- .remove = __devexit_p(fimd_remove),
- .driver = {
- .name = "s3cfb",
- .owner = THIS_MODULE,
- .pm = &fimd_pm_ops,
- },
-};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index a8f201e..5633207 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -22,6 +22,7 @@
#include "drmP.h"
#include "exynos_drm.h"
#include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h"
#define G2D_HW_MAJOR_VER 4
@@ -93,7 +94,7 @@
#define G2D_CMDLIST_POOL_SIZE (G2D_CMDLIST_SIZE * G2D_CMDLIST_NUM)
#define G2D_CMDLIST_DATA_NUM (G2D_CMDLIST_SIZE / sizeof(u32) - 2)
-#define MAX_BUF_ADDR_NR 6
+#define MAX_BUF_ADDR_NR 6
/* cmdlist data structure */
struct g2d_cmdlist {
@@ -111,7 +112,7 @@ struct g2d_cmdlist_node {
struct list_head list;
struct g2d_cmdlist *cmdlist;
unsigned int map_nr;
- void *gem_obj[MAX_BUF_ADDR_NR];
+ void *gem_objs[MAX_BUF_ADDR_NR];
dma_addr_t dma_addr;
struct drm_exynos_pending_g2d_event *event;
@@ -152,7 +153,8 @@ struct g2d_data {
struct kmem_cache *runqueue_slab;
};
-static int g2d_init_cmdlist(struct g2d_data *g2d)
+static int g2d_init_cmdlist(struct g2d_data *g2d,
+ struct exynos_drm_private *drm_priv)
{
struct device *dev = g2d->dev;
struct g2d_cmdlist_node *node = g2d->cmdlist_node;
@@ -171,8 +173,9 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
* pages contained in sg list to iommu table. Command list pool also is
* accessed by dma through device address with using iommu.
*/
- g2d->cmdlist_pool_map = exynos_drm_iommu_map(dev, g2d->cmdlist_pool,
- G2D_CMDLIST_POOL_SIZE);
+ g2d->cmdlist_pool_map = exynos_drm_iommu_map(drm_priv->vmm,
+ g2d->cmdlist_pool,
+ G2D_CMDLIST_POOL_SIZE);
if (!g2d->cmdlist_pool_map) {
dev_err(dev, "failed map to iommu\n");
ret = -EFAULT;
@@ -199,7 +202,7 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
return 0;
err_iommu_unmap:
- exynos_drm_iommu_unmap(dev, g2d->cmdlist_pool_map);
+ exynos_drm_iommu_unmap(drm_priv->vmm, g2d->cmdlist_pool_map);
err:
dma_free_coherent(dev, G2D_CMDLIST_POOL_SIZE, g2d->cmdlist_pool_virt,
g2d->cmdlist_pool);
@@ -208,13 +211,18 @@ err:
static void g2d_fini_cmdlist(struct g2d_data *g2d)
{
- struct device *dev = g2d->dev;
+ struct exynos_drm_private *drm_priv;
+ struct exynos_drm_subdrv *subdrv = &g2d->subdrv;
+
+ drm_priv = subdrv->drm_dev->dev_private;
- exynos_drm_iommu_unmap(dev, g2d->cmdlist_pool_map);
+ if (drm_priv->vmm)
+ exynos_drm_iommu_unmap(drm_priv->vmm, g2d->cmdlist_pool_map);
kfree(g2d->cmdlist_node);
- dma_free_coherent(dev, G2D_CMDLIST_POOL_SIZE, g2d->cmdlist_pool_virt,
- g2d->cmdlist_pool);
+ dma_free_coherent(g2d->dev, G2D_CMDLIST_POOL_SIZE,
+ g2d->cmdlist_pool_virt,
+ g2d->cmdlist_pool);
}
static struct g2d_cmdlist_node *g2d_get_cmdlist(struct g2d_data *g2d)
@@ -269,70 +277,48 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
struct drm_device *drm_dev,
struct drm_file *file)
{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
struct g2d_cmdlist *cmdlist = node->cmdlist;
- struct iommu_gem_map_params params;
- unsigned int gem_handle;
- dma_addr_t addr;
int offset;
int i;
- params.dev = g2d->dev;
- params.drm_dev = drm_dev;
- params.file = file;
-
for (i = 0; i < node->map_nr; i++) {
+ unsigned int gem_handle, gem_obj;
+ dma_addr_t *addr;
+
offset = cmdlist->last - (i * 2 + 1);
gem_handle = cmdlist->data[offset];
- addr = exynos_drm_iommu_map_gem(&params,
- &g2d_priv->iommu_map_list,
- gem_handle,
- IOMMU_G2D);
- if (!addr) {
+ addr = exynos_drm_gem_get_dma_addr(drm_dev, gem_handle,
+ file,
+ &gem_obj);
+ if (IS_ERR(addr)) {
node->map_nr = i;
return -EFAULT;
}
- cmdlist->data[offset] = addr;
- node->gem_obj[i] = params.gem_obj;
+ cmdlist->data[offset] = *addr;
+ node->gem_objs[i] = (void *)gem_obj;
}
return 0;
}
-static void g2d_unmap_cmdlist_gem(struct drm_device *drm_dev,
- struct g2d_cmdlist_node *node,
- struct drm_file *file, int dec)
+static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d,
+ struct g2d_cmdlist_node *node)
{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
- struct device *dev = g2d_priv->dev;
- struct g2d_cmdlist *cmdlist = node->cmdlist;
- struct iommu_gem_map_params params;
- struct g2d_data *g2d;
- dma_addr_t addr;
- int offset;
+ struct exynos_drm_subdrv *subdrv = &g2d->subdrv;
int i;
- g2d = dev_get_drvdata(dev);
- if (!g2d)
- return;
-
- params.dev = dev;
- params.drm_dev = drm_dev;
- params.file = file;
-
for (i = 0; i < node->map_nr; i++) {
- offset = cmdlist->last - (i * 2 + 1) - dec;
- addr = cmdlist->data[offset];
+ void *gem_obj = node->gem_objs[i];
- params.gem_obj = node->gem_obj[i];
+ if (gem_obj)
+ exynos_drm_gem_put_dma_addr(subdrv->drm_dev, gem_obj);
- exynos_drm_iommu_unmap_gem(&params, addr,
- IOMMU_G2D);
+ node->gem_objs[i] = NULL;
}
+
+ node->map_nr = 0;
}
static void g2d_dma_start(struct g2d_data *g2d,
@@ -344,7 +330,7 @@ static void g2d_dma_start(struct g2d_data *g2d,
pm_runtime_get_sync(g2d->dev);
clk_enable(g2d->gate_clk);
- pm_qos_update_request(&g2d->pm_qos, 400000);
+ pm_qos_update_request(&g2d->pm_qos, 400200);
/* interrupt enable */
writel_relaxed(G2D_INTEN_ACF | G2D_INTEN_UCF | G2D_INTEN_GCF,
@@ -370,10 +356,18 @@ static struct g2d_runqueue_node *g2d_get_runqueue_node(struct g2d_data *g2d)
static void g2d_free_runqueue_node(struct g2d_data *g2d,
struct g2d_runqueue_node *runqueue_node)
{
+ struct g2d_cmdlist_node *node;
+
if (!runqueue_node)
return;
mutex_lock(&g2d->cmdlist_mutex);
+ /*
+ * commands in run_cmdlist have been completed so unmap all gem
+ * objects in each command node so that they are unreferenced.
+ */
+ list_for_each_entry(node, &runqueue_node->run_cmdlist, list)
+ g2d_unmap_cmdlist_gem(g2d, node);
list_splice_tail_init(&runqueue_node->run_cmdlist, &g2d->free_cmdlist);
mutex_unlock(&g2d->cmdlist_mutex);
@@ -398,7 +392,15 @@ static void g2d_runqueue_worker(struct work_struct *work)
clk_disable(g2d->gate_clk);
pm_runtime_put_sync(g2d->dev);
- complete(&g2d->runqueue_node->complete);
+ /* if async mode, do not call complete. */
+ if (!g2d->runqueue_node->async)
+ complete(&g2d->runqueue_node->complete);
+
+ /*
+ * if async mode, run_cmdlist of runqueue_node is not freed
+ * at exynos_g2d_exec_ioctl once complete because wait_for_completion
+ * wasn't called there so free it here.
+ */
if (g2d->runqueue_node->async)
g2d_free_runqueue_node(g2d, g2d->runqueue_node);
@@ -444,12 +446,14 @@ static irqreturn_t g2d_irq_handler(int irq, void *dev_id)
writel_relaxed(pending, g2d->regs + G2D_INTC_PEND);
if (pending & G2D_INTP_GCMD_FIN) {
- u32 cmdlist_no = readl_relaxed(g2d->regs + G2D_DMA_STATUS);
+ u32 value, list_done_count;
- cmdlist_no = (cmdlist_no & G2D_DMA_LIST_DONE_COUNT) >>
+ value = readl_relaxed(g2d->regs + G2D_DMA_STATUS);
+
+ list_done_count = (value & G2D_DMA_LIST_DONE_COUNT) >>
G2D_DMA_LIST_DONE_COUNT_OFFSET;
- g2d_finish_event(g2d, cmdlist_no);
+ g2d_finish_event(g2d, list_done_count);
writel_relaxed(0, g2d->regs + G2D_DMA_HOLD_CMD);
if (!(pending & G2D_INTP_ACMD_FIN)) {
@@ -461,6 +465,8 @@ static irqreturn_t g2d_irq_handler(int irq, void *dev_id)
if (pending & G2D_INTP_ACMD_FIN)
queue_work(g2d->g2d_workq, &g2d->runqueue_work);
+ writel_relaxed(pending, g2d->regs + G2D_INTC_PEND);
+
return IRQ_HANDLED;
}
@@ -653,7 +659,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
return 0;
err_unmap:
- g2d_unmap_cmdlist_gem(drm_dev, node, file, 0);
+ g2d_unmap_cmdlist_gem(g2d, node);
err_free_event:
if (node->event) {
spin_lock_irqsave(&drm_dev->event_lock, flags);
@@ -724,11 +730,57 @@ out:
}
EXPORT_SYMBOL_GPL(exynos_g2d_exec_ioctl);
-static int g2d_open(struct drm_device *drm_dev, struct device *dev,
+static int g2d_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
+{
+ struct exynos_drm_private *drm_priv;
+ struct g2d_data *g2d;
+ int ret;
+
+ drm_priv = drm_dev->dev_private;
+
+ g2d = dev_get_drvdata(dev);
+ if (!g2d)
+ return -EFAULT;
+
+ /* allocate dma-aware cmdlist buffer and map it with iommu table. */
+ ret = g2d_init_cmdlist(g2d, drm_priv);
+ if (ret < 0)
+ return ret;
+
+ /* enable iommu to g2d hardware */
+ ret = exynos_drm_iommu_activate(drm_priv->vmm, dev);
+ if (ret < 0) {
+ dev_err(dev, "failed to activate iommu\n");
+ goto err_fini_cmdlist;
+ }
+
+ return ret;
+
+err_fini_cmdlist:
+ g2d_fini_cmdlist(g2d);
+ return ret;
+}
+
+static void g2d_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
+{
+ struct exynos_drm_private *drm_priv;
+
+ drm_priv = drm_dev->dev_private;
+
+ if (drm_priv->vmm)
+ exynos_drm_iommu_deactivate(drm_priv->vmm, dev);
+}
+
+static int g2d_subdrv_open(struct drm_device *drm_dev, struct device *dev,
struct drm_file *file)
{
struct drm_exynos_file_private *file_priv = file->driver_priv;
struct exynos_drm_g2d_private *g2d_priv;
+ struct g2d_data *g2d;
+
+ g2d = dev_get_drvdata(dev);
+ if (!g2d)
+ return -EFAULT;
g2d_priv = kzalloc(sizeof(*g2d_priv), GFP_KERNEL);
if (!g2d_priv) {
@@ -741,20 +793,17 @@ static int g2d_open(struct drm_device *drm_dev, struct device *dev,
INIT_LIST_HEAD(&g2d_priv->inuse_cmdlist);
INIT_LIST_HEAD(&g2d_priv->event_list);
- INIT_LIST_HEAD(&g2d_priv->iommu_map_list);
return 0;
}
-static void g2d_close(struct drm_device *drm_dev, struct device *dev,
+static void g2d_subdrv_close(struct drm_device *drm_dev, struct device *dev,
struct drm_file *file)
{
struct drm_exynos_file_private *file_priv = file->driver_priv;
struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
struct g2d_data *g2d;
struct g2d_cmdlist_node *node, *n;
- struct iommu_info_node *im, *t_im;
- struct iommu_gem_map_params params;
if (!dev)
return;
@@ -764,27 +813,18 @@ static void g2d_close(struct drm_device *drm_dev, struct device *dev,
return;
mutex_lock(&g2d->cmdlist_mutex);
- list_for_each_entry_safe(node, n, &g2d_priv->inuse_cmdlist, list)
+ list_for_each_entry_safe(node, n, &g2d_priv->inuse_cmdlist, list) {
+ /*
+ * unmap all gem objects not completed.
+ *
+ * P.S. if current process was terminated forcely then
+ * there may be some commands in inuse_cmdlist so unmap
+ * them.
+ */
+ g2d_unmap_cmdlist_gem(g2d, node);
list_move_tail(&node->list, &g2d->free_cmdlist);
- mutex_unlock(&g2d->cmdlist_mutex);
-
- params.dev = dev;
- params.drm_dev = drm_dev;
- params.file = file;
-
- /*
- * unmap all device address spaces from iommu table and
- * release all lists.
- */
- list_for_each_entry_safe(im, t_im, &g2d_priv->iommu_map_list, list) {
- params.gem_obj = im->gem_obj;
-
- exynos_drm_iommu_unmap_gem(&params, im->dma_addr,
- IOMMU_G2D);
- list_del(&im->list);
- kfree(im);
- im = NULL;
}
+ mutex_unlock(&g2d->cmdlist_mutex);
kfree(file_priv->g2d_priv);
}
@@ -826,29 +866,11 @@ static int __devinit g2d_probe(struct platform_device *pdev)
mutex_init(&g2d->cmdlist_mutex);
mutex_init(&g2d->runqueue_mutex);
- /* setup device address space for g2d iommu */
- ret = exynos_drm_iommu_setup(dev);
- if (ret < 0) {
- dev_err(dev, "failed to setup iommu\n");
- goto err_destroy_workqueue;
- }
-
- /* enable iommu to g2d hardware */
- ret = exynos_drm_iommu_activate(dev);
- if (ret < 0) {
- dev_err(dev, "failed to activate iommu\n");
- goto err_iommu_cleanup;
- }
-
- ret = g2d_init_cmdlist(g2d);
- if (ret < 0)
- goto err_iommu_deactivate;
-
g2d->gate_clk = clk_get(dev, "fimg2d");
if (IS_ERR(g2d->gate_clk)) {
dev_err(dev, "failed to get gate clock\n");
ret = PTR_ERR(g2d->gate_clk);
- goto err_fini_cmdlist;
+ goto err_destory_workqueue;
}
pm_runtime_enable(dev);
@@ -892,8 +914,10 @@ static int __devinit g2d_probe(struct platform_device *pdev)
subdrv = &g2d->subdrv;
subdrv->dev = dev;
- subdrv->open = g2d_open;
- subdrv->close = g2d_close;
+ subdrv->probe = g2d_subdrv_probe;
+ subdrv->remove = g2d_subdrv_remove;
+ subdrv->open = g2d_subdrv_open;
+ subdrv->close = g2d_subdrv_close;
ret = exynos_drm_subdrv_register(subdrv);
if (ret < 0) {
@@ -918,13 +942,7 @@ err_release_res:
err_put_clk:
pm_runtime_disable(dev);
clk_put(g2d->gate_clk);
-err_fini_cmdlist:
- g2d_fini_cmdlist(g2d);
-err_iommu_deactivate:
- exynos_drm_iommu_deactivate(dev);
-err_iommu_cleanup:
- exynos_drm_iommu_cleanup(dev);
-err_destroy_workqueue:
+err_destory_workqueue:
destroy_workqueue(g2d->g2d_workq);
err_destroy_slab:
kmem_cache_destroy(g2d->runqueue_slab);
@@ -955,8 +973,6 @@ static int __devexit g2d_remove(struct platform_device *pdev)
clk_put(g2d->gate_clk);
g2d_fini_cmdlist(g2d);
- exynos_drm_iommu_deactivate(&pdev->dev);
- exynos_drm_iommu_cleanup(&pdev->dev);
destroy_workqueue(g2d->g2d_workq);
kmem_cache_destroy(g2d->runqueue_slab);
kfree(g2d);
@@ -968,6 +984,8 @@ static int __devexit g2d_remove(struct platform_device *pdev)
static int g2d_suspend(struct device *dev)
{
struct g2d_data *g2d = dev_get_drvdata(dev);
+ struct drm_device *drm_dev = g2d->subdrv.drm_dev;
+ struct exynos_drm_private *drm_priv = drm_dev->dev_private;
mutex_lock(&g2d->runqueue_mutex);
g2d->suspended = true;
@@ -979,12 +997,25 @@ static int g2d_suspend(struct device *dev)
flush_work_sync(&g2d->runqueue_work);
+ /* disable iommu to g2d device. */
+ exynos_drm_iommu_deactivate(drm_priv->vmm, dev);
+
return 0;
}
static int g2d_resume(struct device *dev)
{
struct g2d_data *g2d = dev_get_drvdata(dev);
+ struct drm_device *drm_dev = g2d->subdrv.drm_dev;
+ struct exynos_drm_private *drm_priv = drm_dev->dev_private;
+ int ret;
+
+ /* enable iommu to g2d hardware */
+ ret = exynos_drm_iommu_activate(drm_priv->vmm, dev);
+ if (ret < 0) {
+ dev_err(dev, "failed to activate iommu\n");
+ return ret;
+ }
g2d->suspended = false;
g2d_exec_runqueue(g2d);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 35d2cd9..7d12f6c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -35,6 +35,8 @@
#include "exynos_drm_buf.h"
#include "exynos_drm_iommu.h"
+#define USERPTR_MAX_SIZE SZ_64M
+
static struct exynos_drm_private_cb *private_cb;
void exynos_drm_priv_cb_register(struct exynos_drm_private_cb *cb)
@@ -132,6 +134,45 @@ static void put_vma(struct vm_area_struct *vma)
kfree(vma);
}
+/*
+ * lock_userptr_vma - lock VMAs within user address space
+ *
+ * this function locks vma within user address space to avoid pages
+ * to the userspace from being swapped out.
+ * if this vma isn't locked, the pages to the userspace could be swapped out
+ * so unprivileged user might access different pages and dma of any device
+ * could access physical memory region not intended once swap-in.
+ */
+static int lock_userptr_vma(struct exynos_drm_gem_buf *buf, unsigned int lock)
+{
+ struct vm_area_struct *vma;
+ unsigned long start, end;
+
+ start = buf->userptr;
+ end = buf->userptr + buf->size - 1;
+
+ down_write(&current->mm->mmap_sem);
+
+ do {
+ vma = find_vma(current->mm, start);
+ if (!vma) {
+ up_write(&current->mm->mmap_sem);
+ return -EFAULT;
+ }
+
+ if (lock)
+ vma->vm_flags |= VM_LOCKED;
+ else
+ vma->vm_flags &= ~VM_LOCKED;
+
+ start = vma->vm_end + 1;
+ } while (vma->vm_end < end);
+
+ up_write(&current->mm->mmap_sem);
+
+ return 0;
+}
+
static void update_vm_cache_attr(struct exynos_drm_gem_obj *obj,
struct vm_area_struct *vma)
{
@@ -165,25 +206,17 @@ out:
struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
gfp_t gfpmask)
{
- struct inode *inode;
- struct address_space *mapping;
struct page *p, **pages;
int i, npages;
- /* This is the shared memory object that backs the GEM resource */
- inode = obj->filp->f_path.dentry->d_inode;
- mapping = inode->i_mapping;
-
npages = obj->size >> PAGE_SHIFT;
pages = drm_malloc_ab(npages, sizeof(struct page *));
if (pages == NULL)
return ERR_PTR(-ENOMEM);
- gfpmask |= mapping_gfp_mask(mapping);
-
for (i = 0; i < npages; i++) {
- p = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
+ p = alloc_page(gfpmask);
if (IS_ERR(p))
goto fail;
pages[i] = p;
@@ -192,31 +225,22 @@ struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
return pages;
fail:
- while (i--)
- page_cache_release(pages[i]);
+ while (--i)
+ __free_page(pages[i]);
drm_free_large(pages);
return ERR_PTR(PTR_ERR(p));
}
static void exynos_gem_put_pages(struct drm_gem_object *obj,
- struct page **pages,
- bool dirty, bool accessed)
+ struct page **pages)
{
- int i, npages;
+ int npages;
npages = obj->size >> PAGE_SHIFT;
- for (i = 0; i < npages; i++) {
- if (dirty)
- set_page_dirty(pages[i]);
-
- if (accessed)
- mark_page_accessed(pages[i]);
-
- /* Undo the reference we took when populating the table */
- page_cache_release(pages[i]);
- }
+ while (--npages >= 0)
+ __free_page(pages[npages]);
drm_free_large(pages);
}
@@ -236,7 +260,7 @@ static int exynos_drm_gem_map_pages(struct drm_gem_object *obj,
pfn = page_to_pfn(buf->pages[page_offset++]);
} else
- pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;
+ pfn = (buf->paddr >> PAGE_SHIFT) + page_offset;
return vm_insert_mixed(vma, f_vaddr, pfn);
}
@@ -255,7 +279,7 @@ static int exynos_drm_gem_get_pages(struct drm_gem_object *obj)
return -EINVAL;
}
- pages = exynos_gem_get_pages(obj, GFP_KERNEL);
+ pages = exynos_gem_get_pages(obj, GFP_HIGHUSER_MOVABLE);
if (IS_ERR(pages)) {
DRM_ERROR("failed to get pages.\n");
return PTR_ERR(pages);
@@ -288,15 +312,13 @@ static int exynos_drm_gem_get_pages(struct drm_gem_object *obj)
sgl = sg_next(sgl);
}
- /* add some codes for UNCACHED type here. TODO */
-
buf->pages = pages;
return ret;
err1:
kfree(buf->sgt);
buf->sgt = NULL;
err:
- exynos_gem_put_pages(obj, pages, true, false);
+ exynos_gem_put_pages(obj, pages);
return ret;
}
@@ -314,7 +336,7 @@ static void exynos_drm_gem_put_pages(struct drm_gem_object *obj)
kfree(buf->sgt);
buf->sgt = NULL;
- exynos_gem_put_pages(obj, buf->pages, true, false);
+ exynos_gem_put_pages(obj, buf->pages);
buf->pages = NULL;
/* add some codes for UNCACHED type here. TODO */
@@ -338,6 +360,9 @@ static void exynos_drm_put_userptr(struct drm_gem_object *obj)
npages = buf->size >> PAGE_SHIFT;
+ if (exynos_gem_obj->flags & EXYNOS_BO_USERPTR && !buf->pfnmap)
+ lock_userptr_vma(buf, 0);
+
npages--;
while (npages >= 0) {
if (buf->write)
@@ -381,10 +406,12 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
{
struct drm_gem_object *obj;
struct exynos_drm_gem_buf *buf;
+ struct exynos_drm_private *private;
DRM_DEBUG_KMS("%s\n", __FILE__);
obj = &exynos_gem_obj->base;
+ private = obj->dev->dev_private;
buf = exynos_gem_obj->buffer;
DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count));
@@ -401,6 +428,18 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
if (!buf->pages)
return;
+ /*
+ * do not release memory region from exporter.
+ *
+ * the region will be released by exporter
+ * once dmabuf's refcount becomes 0.
+ */
+ if (obj->import_attach)
+ goto out;
+
+ if (private->vmm)
+ exynos_drm_iommu_unmap_gem(obj);
+
if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG)
exynos_drm_gem_put_pages(obj);
else if (exynos_gem_obj->flags & EXYNOS_BO_USERPTR)
@@ -408,6 +447,7 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
else
exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, buf);
+out:
exynos_drm_fini_buf(obj->dev, buf);
exynos_gem_obj->buffer = NULL;
@@ -441,6 +481,27 @@ struct exynos_drm_gem_obj *exynos_drm_gem_get_obj(struct drm_device *dev,
return exynos_gem_obj;
}
+unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
+ unsigned int gem_handle,
+ struct drm_file *file_priv)
+{
+ struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct drm_gem_object *obj;
+
+ obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
+ if (!obj) {
+ DRM_ERROR("failed to lookup gem object.\n");
+ return 0;
+ }
+
+ exynos_gem_obj = to_exynos_gem_obj(obj);
+
+ drm_gem_object_unreference_unlocked(obj);
+
+ return exynos_gem_obj->buffer->size;
+}
+
+
struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
unsigned long size)
{
@@ -474,7 +535,9 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
unsigned long size)
{
struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_private *private = dev->dev_private;
struct exynos_drm_gem_buf *buf;
+ unsigned long packed_size = size;
int ret;
if (!size) {
@@ -499,6 +562,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
goto err_fini_buf;
}
+ exynos_gem_obj->packed_size = packed_size;
exynos_gem_obj->buffer = buf;
/* set memory type and cache attribute from user side. */
@@ -522,6 +586,31 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
}
}
+ if (private->vmm) {
+ exynos_gem_obj->vmm = private->vmm;
+
+ buf->dev_addr = exynos_drm_iommu_map_gem(dev,
+ &exynos_gem_obj->base);
+ if (!buf->dev_addr) {
+ DRM_ERROR("failed to map gem with iommu table.\n");
+ ret = -EFAULT;
+
+ if (flags & EXYNOS_BO_NONCONTIG)
+ exynos_drm_gem_put_pages(&exynos_gem_obj->base);
+ else
+ exynos_drm_free_buf(dev, flags, buf);
+
+ drm_gem_object_release(&exynos_gem_obj->base);
+
+ goto err_fini_buf;
+ }
+
+ buf->dma_addr = buf->dev_addr;
+ } else
+ buf->dma_addr = buf->paddr;
+
+ DRM_DEBUG_KMS("dma_addr = 0x%x\n", buf->dma_addr);
+
return exynos_gem_obj;
err_fini_buf:
@@ -549,63 +638,49 @@ int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
return ret;
}
- return 0;
+ return ret;
}
void *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
unsigned int gem_handle,
- struct drm_file *file_priv)
+ struct drm_file *filp,
+ unsigned int *gem_obj)
{
struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem_buf *buf;
struct drm_gem_object *obj;
- obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
+ obj = drm_gem_object_lookup(dev, filp, gem_handle);
if (!obj) {
DRM_ERROR("failed to lookup gem object.\n");
return ERR_PTR(-EINVAL);
}
exynos_gem_obj = to_exynos_gem_obj(obj);
+ buf = exynos_gem_obj->buffer;
- if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
- DRM_DEBUG_KMS("not support NONCONTIG type.\n");
- drm_gem_object_unreference_unlocked(obj);
+ *gem_obj = (unsigned int)obj;
- /* TODO */
- return ERR_PTR(-EINVAL);
- }
-
- return &exynos_gem_obj->buffer->dma_addr;
+ return &buf->dma_addr;
}
-void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
- unsigned int gem_handle,
- struct drm_file *file_priv)
+void exynos_drm_gem_put_dma_addr(struct drm_device *dev, void *gem_obj)
{
struct exynos_drm_gem_obj *exynos_gem_obj;
struct drm_gem_object *obj;
- obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object.\n");
+ if (!gem_obj)
return;
- }
- exynos_gem_obj = to_exynos_gem_obj(obj);
+ /* use gem handle instead of object. TODO */
- if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
- DRM_DEBUG_KMS("not support NONCONTIG type.\n");
- drm_gem_object_unreference_unlocked(obj);
+ obj = gem_obj;
- /* TODO */
- return;
- }
-
- drm_gem_object_unreference_unlocked(obj);
+ exynos_gem_obj = to_exynos_gem_obj(obj);
/*
- * decrease obj->refcount one more time because we has already
- * increased it at exynos_drm_gem_get_dma_addr().
+ * unreference this gem object because this had already been
+ * referenced at exynos_drm_gem_get_dma_addr().
*/
drm_gem_object_unreference_unlocked(obj);
}
@@ -681,7 +756,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
* get page frame number to physical memory to be mapped
* to user space.
*/
- pfn = ((unsigned long)exynos_gem_obj->buffer->dma_addr) >>
+ pfn = ((unsigned long)exynos_gem_obj->buffer->paddr) >>
PAGE_SHIFT;
DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn);
@@ -749,7 +824,9 @@ static int exynos_drm_get_userptr(struct drm_device *dev,
unsigned long npages = 0;
struct vm_area_struct *vma;
struct exynos_drm_gem_buf *buf = obj->buffer;
+ int ret;
+ down_read(&current->mm->mmap_sem);
vma = find_vma(current->mm, userptr);
/* the memory region mmaped with VM_PFNMAP. */
@@ -767,11 +844,11 @@ static int exynos_drm_get_userptr(struct drm_device *dev,
for (prev_pfn = 0; start < end; start += PAGE_SIZE) {
ret = follow_pfn(vma, start, &this_pfn);
if (ret)
- return ret;
+ goto err;
if (prev_pfn == 0) {
pa = this_pfn << PAGE_SHIFT;
- buf->dma_addr = pa + offset;
+ buf->paddr = pa + offset;
} else if (this_pfn != prev_pfn + 1) {
ret = -EINVAL;
goto err;
@@ -791,14 +868,30 @@ static int exynos_drm_get_userptr(struct drm_device *dev,
goto err;
}
+ up_read(&current->mm->mmap_sem);
buf->pfnmap = true;
return npages;
err:
- buf->dma_addr = 0;
+ buf->paddr = 0;
+ up_read(&current->mm->mmap_sem);
+
return ret;
}
+ up_read(&current->mm->mmap_sem);
+
+ /*
+ * lock the vma within userptr to avoid userspace buffer
+ * from being swapped out.
+ */
+ ret = lock_userptr_vma(buf, 1);
+ if (ret < 0) {
+ DRM_ERROR("failed to lock vma for userptr.\n");
+ lock_userptr_vma(buf, 0);
+ return 0;
+ }
+
buf->write = write;
npages = buf->size >> PAGE_SHIFT;
@@ -809,6 +902,7 @@ err:
if (get_npages != npages)
DRM_ERROR("failed to get user_pages.\n");
+ buf->userptr = userptr;
buf->pfnmap = false;
return get_npages;
@@ -817,11 +911,12 @@ err:
int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ struct exynos_drm_private *priv = dev->dev_private;
struct exynos_drm_gem_obj *exynos_gem_obj;
struct drm_exynos_gem_userptr *args = data;
struct exynos_drm_gem_buf *buf;
struct scatterlist *sgl;
- unsigned long size, userptr;
+ unsigned long size, userptr, packed_size;
unsigned int npages;
int ret, get_npages;
@@ -836,7 +931,15 @@ int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
if (ret)
return ret;
+ packed_size = args->size;
+
size = roundup_gem_size(args->size, EXYNOS_BO_USERPTR);
+
+ if (size > priv->userptr_limit) {
+ DRM_ERROR("excessed maximum size of userptr.\n");
+ return -EINVAL;
+ }
+
userptr = args->userptr;
buf = exynos_drm_init_buf(dev, size);
@@ -849,6 +952,8 @@ int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
goto err_free_buffer;
}
+ exynos_gem_obj->packed_size = packed_size;
+
buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
if (!buf->sgt) {
DRM_ERROR("failed to allocate buf->sgt.\n");
@@ -909,8 +1014,30 @@ int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
/* always use EXYNOS_BO_USERPTR as memory type for userptr. */
exynos_gem_obj->flags |= EXYNOS_BO_USERPTR;
+ if (priv->vmm) {
+ exynos_gem_obj->vmm = priv->vmm;
+
+ buf->dev_addr = exynos_drm_iommu_map_gem(dev,
+ &exynos_gem_obj->base);
+ if (!buf->dev_addr) {
+ DRM_ERROR("failed to map gem with iommu table.\n");
+ ret = -EFAULT;
+
+ exynos_drm_free_buf(dev, exynos_gem_obj->flags, buf);
+
+ drm_gem_object_release(&exynos_gem_obj->base);
+
+ goto err_release_handle;
+ }
+
+ buf->dma_addr = buf->dev_addr;
+ } else
+ buf->dma_addr = buf->paddr;
+
return 0;
+err_release_handle:
+ drm_gem_handle_delete(file_priv, args->handle);
err_release_userptr:
get_npages--;
while (get_npages >= 0)
@@ -957,6 +1084,26 @@ int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
return 0;
}
+int exynos_drm_gem_user_limit_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *filp)
+{
+ struct exynos_drm_private *priv = dev->dev_private;
+ struct drm_exynos_user_limit *limit = data;
+
+ if (limit->userptr_limit < PAGE_SIZE ||
+ limit->userptr_limit > USERPTR_MAX_SIZE) {
+ DRM_DEBUG_KMS("invalid userptr_limit size.\n");
+ return -EINVAL;
+ }
+
+ if (priv->userptr_limit == limit->userptr_limit)
+ return 0;
+
+ priv->userptr_limit = limit->userptr_limit;
+
+ return 0;
+}
+
int exynos_drm_gem_export_ump_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
@@ -1034,13 +1181,16 @@ static int exynos_gem_l1_cache_ops(struct drm_device *drm_dev,
}
static int exynos_gem_l2_cache_ops(struct drm_device *drm_dev,
- struct drm_exynos_gem_cache_op *op) {
- phys_addr_t phy_start, phy_end;
-
+ struct drm_file *filp,
+ struct drm_exynos_gem_cache_op *op)
+{
if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE ||
op->flags & EXYNOS_DRM_CACHE_INV_RANGE ||
op->flags & EXYNOS_DRM_CACHE_CLN_RANGE) {
+ unsigned long virt_start = op->usr_addr, pfn;
+ phys_addr_t phy_start, phy_end;
struct vm_area_struct *vma;
+ int ret;
down_read(&current->mm->mmap_sem);
vma = find_vma(current->mm, op->usr_addr);
@@ -1052,44 +1202,90 @@ static int exynos_gem_l2_cache_ops(struct drm_device *drm_dev,
}
/*
- * for range flush to l2 cache, mmaped memory region should
- * be physically continuous because l2 cache uses PIPT.
+ * Range operation to l2 cache(PIPT)
*/
if (vma && (vma->vm_flags & VM_PFNMAP)) {
- unsigned long virt_start = op->usr_addr, pfn;
- int ret;
-
ret = follow_pfn(vma, virt_start, &pfn);
if (ret < 0) {
- DRM_ERROR("failed to get pfn from usr_addr.\n");
+ DRM_ERROR("failed to get pfn.\n");
return ret;
}
+ /*
+ * the memory region with VM_PFNMAP is contiguous
+ * physically so do range operagion just one time.
+ */
phy_start = pfn << PAGE_SHIFT;
phy_end = phy_start + op->size;
+
+ if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE)
+ outer_flush_range(phy_start, phy_end);
+ else if (op->flags & EXYNOS_DRM_CACHE_INV_RANGE)
+ outer_inv_range(phy_start, phy_end);
+ else if (op->flags & EXYNOS_DRM_CACHE_CLN_RANGE)
+ outer_clean_range(phy_start, phy_end);
+
+ return 0;
} else {
- DRM_ERROR("not mmaped memory region with PFNMAP.\n");
- return -EINVAL;
+ struct exynos_drm_gem_obj *exynos_obj;
+ struct exynos_drm_gem_buf *buf;
+ struct drm_gem_object *obj;
+ struct scatterlist *sgl;
+ unsigned int npages, i = 0;
+
+ mutex_lock(&drm_dev->struct_mutex);
+
+ obj = drm_gem_object_lookup(drm_dev, filp,
+ op->gem_handle);
+ if (!obj) {
+ DRM_ERROR("failed to lookup gem object.\n");
+ mutex_unlock(&drm_dev->struct_mutex);
+ return -EINVAL;
+ }
+
+ exynos_obj = to_exynos_gem_obj(obj);
+ buf = exynos_obj->buffer;
+ npages = buf->size >> PAGE_SHIFT;
+ sgl = buf->sgt->sgl;
+
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&drm_dev->struct_mutex);
+
+ /*
+ * in this case, the memory region is non-contiguous
+ * physically so do range operation to all the pages.
+ */
+ while (i < npages) {
+ phy_start = sg_dma_address(sgl);
+ phy_end = phy_start + buf->page_size;
+
+ if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE)
+ outer_flush_range(phy_start, phy_end);
+ else if (op->flags & EXYNOS_DRM_CACHE_INV_RANGE)
+ outer_inv_range(phy_start, phy_end);
+ else if (op->flags & EXYNOS_DRM_CACHE_CLN_RANGE)
+ outer_clean_range(phy_start, phy_end);
+
+ i++;
+ sgl = sg_next(sgl);
+ }
+
+ return 0;
}
}
if (op->flags & EXYNOS_DRM_CACHE_FSH_ALL)
outer_flush_all();
- else if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE)
- outer_flush_range(phy_start, phy_end);
else if (op->flags & EXYNOS_DRM_CACHE_INV_ALL)
outer_inv_all();
else if (op->flags & EXYNOS_DRM_CACHE_CLN_ALL)
outer_clean_all();
- else if (op->flags & EXYNOS_DRM_CACHE_INV_RANGE)
- outer_inv_range(phy_start, phy_end);
- else if (op->flags & EXYNOS_DRM_CACHE_CLN_RANGE)
- outer_clean_range(phy_start, phy_end);
else {
DRM_ERROR("invalid l2 cache operation.\n");
return -EINVAL;
}
+
return 0;
}
@@ -1105,6 +1301,33 @@ int exynos_drm_gem_cache_op_ioctl(struct drm_device *drm_dev, void *data,
if (ret)
return -EINVAL;
+ /*
+ * do cache operation for all cache range if op->size is bigger
+ * than SZ_1M because cache range operation with bit size has
+ * big cost.
+ */
+ if (op->size >= SZ_1M) {
+ if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE) {
+ if (op->flags & EXYNOS_DRM_L1_CACHE)
+ __cpuc_flush_user_all();
+
+ if (op->flags & EXYNOS_DRM_L2_CACHE)
+ outer_flush_all();
+
+ return 0;
+ } else if (op->flags & EXYNOS_DRM_CACHE_INV_RANGE) {
+ if (op->flags & EXYNOS_DRM_L2_CACHE)
+ outer_inv_all();
+
+ return 0;
+ } else if (op->flags & EXYNOS_DRM_CACHE_CLN_RANGE) {
+ if (op->flags & EXYNOS_DRM_L2_CACHE)
+ outer_clean_all();
+
+ return 0;
+ }
+ }
+
if (op->flags & EXYNOS_DRM_L1_CACHE ||
op->flags & EXYNOS_DRM_ALL_CACHES) {
ret = exynos_gem_l1_cache_ops(drm_dev, op);
@@ -1114,7 +1337,7 @@ int exynos_drm_gem_cache_op_ioctl(struct drm_device *drm_dev, void *data,
if (op->flags & EXYNOS_DRM_L2_CACHE ||
op->flags & EXYNOS_DRM_ALL_CACHES)
- ret = exynos_gem_l2_cache_ops(drm_dev, op);
+ ret = exynos_gem_l2_cache_ops(drm_dev, file_priv, op);
err:
return ret;
}
@@ -1150,7 +1373,7 @@ int exynos_drm_gem_get_phy_ioctl(struct drm_device *drm_dev, void *data,
return -EINVAL;
}
- get_phy->phy_addr = exynos_gem_obj->buffer->dma_addr;
+ get_phy->phy_addr = exynos_gem_obj->buffer->paddr;
get_phy->size = exynos_gem_obj->buffer->size;
drm_gem_object_unreference(obj);
@@ -1164,24 +1387,34 @@ int exynos_drm_gem_phy_imp_ioctl(struct drm_device *drm_dev, void *data,
{
struct drm_exynos_gem_phy_imp *args = data;
struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_private *private = drm_dev->dev_private;
struct exynos_drm_gem_buf *buffer;
+ unsigned long size, packed_size;
+ unsigned int flags = EXYNOS_BO_CONTIG;
+ unsigned int npages, i = 0;
+ struct scatterlist *sgl;
+ dma_addr_t start_addr;
int ret = 0;
DRM_DEBUG_KMS("%s\n", __FILE__);
- exynos_gem_obj = exynos_drm_gem_init(drm_dev, args->size);
+ packed_size = args->size;
+ size = roundup_gem_size(args->size, flags);
+
+ exynos_gem_obj = exynos_drm_gem_init(drm_dev, size);
if (!exynos_gem_obj)
return -ENOMEM;
- buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+ buffer = exynos_drm_init_buf(drm_dev, size);
if (!buffer) {
DRM_DEBUG_KMS("failed to allocate buffer\n");
ret = -ENOMEM;
- goto err;
+ goto err_release_gem_obj;
}
- buffer->dma_addr = (dma_addr_t)args->phy_addr;
- buffer->size = args->size;
+ exynos_gem_obj->packed_size = packed_size;
+ buffer->paddr = (dma_addr_t)args->phy_addr;
+ buffer->size = size;
/*
* if shared is true, this bufer wouldn't be released.
@@ -1194,15 +1427,90 @@ int exynos_drm_gem_phy_imp_ioctl(struct drm_device *drm_dev, void *data,
ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
&args->gem_handle);
if (ret)
- goto err_kfree_buffer;
+ goto err_fini_buf;
DRM_DEBUG_KMS("got gem handle = 0x%x\n", args->gem_handle);
+ if (buffer->size >= SZ_1M) {
+ npages = buffer->size >> SECTION_SHIFT;
+ buffer->page_size = SECTION_SIZE;
+ } else if (buffer->size >= SZ_64K) {
+ npages = buffer->size >> 16;
+ buffer->page_size = SZ_64K;
+ } else {
+ npages = buffer->size >> PAGE_SHIFT;
+ buffer->page_size = PAGE_SIZE;
+ }
+
+ buffer->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
+ if (!buffer->sgt) {
+ DRM_ERROR("failed to allocate sg table.\n");
+ ret = -ENOMEM;
+ goto err_release_handle;
+ }
+
+ ret = sg_alloc_table(buffer->sgt, npages, GFP_KERNEL);
+ if (ret < 0) {
+ DRM_ERROR("failed to initialize sg table.\n");
+ goto err_free_sgt;
+ }
+
+ buffer->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
+ if (!buffer->pages) {
+ DRM_ERROR("failed to allocate pages.\n");
+ ret = -ENOMEM;
+ goto err_sg_free_table;
+ }
+
+ sgl = buffer->sgt->sgl;
+ start_addr = buffer->paddr;
+
+ while (i < npages) {
+ buffer->pages[i] = phys_to_page(start_addr);
+ sg_set_page(sgl, buffer->pages[i], buffer->page_size, 0);
+ sg_dma_address(sgl) = start_addr;
+ start_addr += buffer->page_size;
+ sgl = sg_next(sgl);
+ i++;
+ }
+
+ if (private->vmm) {
+ exynos_gem_obj->vmm = private->vmm;
+
+ buffer->dev_addr = exynos_drm_iommu_map_gem(drm_dev,
+ &exynos_gem_obj->base);
+ if (!buffer->dev_addr) {
+ DRM_ERROR("failed to map gem with iommu table.\n");
+ ret = -EFAULT;
+
+ exynos_drm_free_buf(drm_dev, flags, buffer);
+
+ drm_gem_object_release(&exynos_gem_obj->base);
+
+ goto err_free_pages;
+ }
+
+ buffer->dma_addr = buffer->dev_addr;
+ } else
+ buffer->dma_addr = buffer->paddr;
+
+ DRM_DEBUG_KMS("dma_addr = 0x%x\n", buffer->dma_addr);
+
return 0;
-err_kfree_buffer:
- kfree(buffer);
-err:
+err_free_pages:
+ kfree(buffer->pages);
+ buffer->pages = NULL;
+err_sg_free_table:
+ sg_free_table(buffer->sgt);
+err_free_sgt:
+ kfree(buffer->sgt);
+ buffer->sgt = NULL;
+err_release_handle:
+ drm_gem_handle_delete(file_priv, args->gem_handle);
+err_fini_buf:
+ exynos_drm_fini_buf(drm_dev, buffer);
+err_release_gem_obj:
drm_gem_object_release(&exynos_gem_obj->base);
kfree(exynos_gem_obj);
return ret;
@@ -1267,7 +1575,6 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
struct drm_device *dev, uint32_t handle,
uint64_t *offset)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
struct drm_gem_object *obj;
int ret = 0;
@@ -1288,15 +1595,13 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
goto unlock;
}
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- if (!exynos_gem_obj->base.map_list.map) {
- ret = drm_gem_create_mmap_offset(&exynos_gem_obj->base);
+ if (!obj->map_list.map) {
+ ret = drm_gem_create_mmap_offset(obj);
if (ret)
goto out;
}
- *offset = (u64)exynos_gem_obj->base.map_list.hash.key << PAGE_SHIFT;
+ *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
out:
@@ -1331,53 +1636,9 @@ int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
void exynos_drm_gem_close_object(struct drm_gem_object *obj,
struct drm_file *file)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct iommu_gem_map_params params;
- unsigned int type = 0;
-
DRM_DEBUG_KMS("%s\n", __FILE__);
- /* check this gem object was mapped to iommu at here. TODO */
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- while (type < MAX_IOMMU_NR) {
- /*
- * unmap device address space already mapped to iommu.
- * - this codes would be performed with user gem release
- * request but in case of no request, when device driver
- * using iommu is released, also same things should be
- * performed by each driver.
- */
- if (exynos_gem_obj->iommu_info.mapped & (1 << type)) {
- dma_addr_t dma_addr;
- struct list_head *list;
-
- params.dev = exynos_gem_obj->iommu_info.devs[type];
- params.drm_dev = obj->dev;
- params.file = file;
- params.gem_obj = exynos_gem_obj;
- dma_addr = exynos_gem_obj->iommu_info.dma_addrs[type];
-
- exynos_drm_iommu_unmap_gem(&params,
- dma_addr,
- type);
-
- exynos_gem_obj->iommu_info.mapped &= ~(1 << type);
- exynos_gem_obj->iommu_info.dma_addrs[type] = 0;
-
- list = exynos_gem_obj->iommu_info.iommu_lists[type];
-
- /*
- * this gem has been unmapped from iommu so also
- * remove a iommu node from current device's own
- * iommu list.
- */
- exynos_drm_remove_iommu_list(list, exynos_gem_obj);
- }
-
- type++;
- }
+ /* TODO */
}
int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index 1227ae3..c6cd6e0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -61,9 +61,10 @@ struct exynos_drm_iommu_info {
* exynos drm gem buffer structure.
*
* @kvaddr: kernel virtual address to allocated memory region.
+ * *userptr: user space address.
* @dma_addr: bus address(accessed by dma) to allocated memory region.
- * - this address could be physical address without IOMMU and
- * device address with IOMMU.
+ * @dev_addr: device address for IOMMU.
+ * @paddr: physical address to allocated buffer.
* @write: whether pages will be written to by the caller.
* @sgt: sg table to transfer page data.
* @pages: contain all pages to allocated memory region.
@@ -71,21 +72,22 @@ struct exynos_drm_iommu_info {
* @size: size of allocated memory region.
* @shared: indicate shared mfc memory region.
* (temporarily used and it should be removed later.)
- * @shared_refcount: a reference count for this buffer being shared with others.
* @pfnmap: indicate whether memory region from userptr is mmaped with
* VM_PFNMAP or not.
*/
struct exynos_drm_gem_buf {
struct device *dev;
void __iomem *kvaddr;
+ unsigned long userptr;
dma_addr_t dma_addr;
+ dma_addr_t dev_addr;
+ dma_addr_t paddr;
unsigned int write;
struct sg_table *sgt;
struct page **pages;
unsigned long page_size;
unsigned long size;
bool shared;
- atomic_t shared_refcount;
bool pfnmap;
};
@@ -102,8 +104,12 @@ struct exynos_drm_gem_buf {
* or at framebuffer creation.
* @iommu_info: contain iommu mapping information to each device driver
* using its own iommu.
- * @size: total memory size to physically non-continuous memory region.
+ * @size: size requested from user, in bytes and this size is aligned
+ * in page unit.
+ * @packed_size: real size of the gem object, in bytes and
+ * this size isn't aligned in page unit.
* @flags: indicate memory type to allocated buffer and cache attruibute.
+ * @vmm: vmm object for iommu framework.
* @priv_handle: handle to specific buffer object.
* @priv_id: unique id to specific buffer object.
*
@@ -115,10 +121,10 @@ struct exynos_drm_gem_obj {
struct exynos_drm_gem_buf *buffer;
struct exynos_drm_iommu_info iommu_info;
unsigned long size;
+ unsigned long packed_size;
struct vm_area_struct *vma;
unsigned int flags;
- void *dma_buf_vmapping;
- int vmapping_count;
+ void *vmm;
unsigned int priv_handle;
unsigned int priv_id;
};
@@ -132,6 +138,9 @@ int register_buf_to_priv_mgr(struct exynos_drm_gem_obj *obj,
struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
+int exynos_drm_gem_user_limit_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *filp);
+
/* destroy a buffer with gem object */
void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj);
@@ -159,16 +168,15 @@ int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
*/
void *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
unsigned int gem_handle,
- struct drm_file *file_priv);
+ struct drm_file *filp,
+ unsigned int *gem_obj);
/*
* put dma address from gem handle and this function could be used for
* other drivers such as 2d/3d acceleration drivers.
* with this function call, gem object reference count would be decreased.
*/
-void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
- unsigned int gem_handle,
- struct drm_file *file_priv);
+void exynos_drm_gem_put_dma_addr(struct drm_device *dev, void *gem_obj);
/* get buffer offset to map to user space. */
int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
@@ -189,6 +197,11 @@ int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+/* get buffer size to gem handle. */
+unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
+ unsigned int gem_handle,
+ struct drm_file *file_priv);
+
/* initialize gem object. */
int exynos_drm_gem_init_object(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
new file mode 100644
index 0000000..d5e3a68
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -0,0 +1,1385 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co.Ltd
+ * Authors:
+ * Eunchul Kim <chulspro.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include "drmP.h"
+#include "drm_backlight.h"
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/cma.h>
+#include <plat/map-base.h>
+
+#include "regs-gsc.h"
+#include <drm/exynos_drm.h>
+#include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_ipp.h"
+#include "exynos_drm_gsc.h"
+
+/*
+ * GSC is stand for General SCaler and
+ * supports image scaler/rotator and input/output DMA operations.
+ * input DMA reads image data from the memory.
+ * output DMA writes image data to memory.
+ * GSC supports image rotation and image effect functions.
+ */
+
+#define GSC_MAX_DEVS 4
+#define GSC_MAX_SRC 8
+#define GSC_MAX_DST 32
+#define GSC_RESET_TIMEOUT 50
+#ifdef CONFIG_SLP_DISP_DEBUG
+#define GSC_MAX_REG 128
+#define GSC_BASE_REG(id) (0x13E00000 + (0x10000 * id))
+#endif
+#define GSC_CLK_RATE 166750000
+#define GSC_BUF_STOP 1
+#define GSC_BUF_START 2
+#define GSC_REG_SZ 32
+#define GSC_WIDTH_ITU_709 1280
+
+#define get_gsc_context(dev) platform_get_drvdata(to_platform_device(dev))
+#define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
+ struct gsc_context, ippdrv);
+#define gsc_read(offset) readl(ctx->regs + (offset));
+#define gsc_write(cfg, offset) writel(cfg, ctx->regs + (offset));
+
+enum gsc_wb {
+ GSC_WB_NONE,
+ GSC_WB_A,
+ GSC_WB_B,
+};
+
+/*
+ * A structure of scaler.
+ *
+ * @range: narrow, wide.
+ * @pre_shfactor: pre sclaer shift factor.
+ * @pre_hratio: horizontal ratio of the prescaler.
+ * @pre_vratio: vertical ratio of the prescaler.
+ * @main_hratio: the main scaler's horizontal ratio.
+ * @main_vratio: the main scaler's vertical ratio.
+ */
+struct gsc_scaler {
+ bool range;
+ u32 pre_shfactor;
+ u32 pre_hratio;
+ u32 pre_vratio;
+ unsigned long main_hratio;
+ unsigned long main_vratio;
+};
+
+/*
+ * A structure of scaler capability.
+ *
+ * find user manual 49.2 features.
+ * @tile_w: tile mode or rotation width.
+ * @tile_h: tile mode or rotation height.
+ * @w: other cases width.
+ * @h: other cases height.
+ */
+struct gsc_capability {
+ /* tile or rotation */
+ u32 tile_w;
+ u32 tile_h;
+ /* other cases */
+ u32 w;
+ u32 h;
+};
+
+/*
+ * A structure of gsc context.
+ *
+ * @ippdrv: prepare initialization using ippdrv.
+ * @regs_res: register resources.
+ * @regs: memory mapped io registers.
+ * @lock: locking of operations.
+ * @gsc_clk: gsc clock.
+ * @sc: scaler infomations.
+ * @capa: scaler capability.
+ * @id: gsc id.
+ * @irq: irq number.
+ * @suspended: qos operations.
+ */
+struct gsc_context {
+ struct exynos_drm_ippdrv ippdrv;
+ struct resource *regs_res;
+ void __iomem *regs;
+ struct mutex lock;
+ struct clk *gsc_clk;
+ struct gsc_scaler sc;
+ struct gsc_capability *capa;
+ int id;
+ int irq;
+ bool suspended;
+};
+
+struct gsc_capability gsc51_capa[GSC_MAX_DEVS] = {
+ {
+ .tile_w = 2048,
+ .tile_h = 2048,
+ .w = 4800,
+ .h = 3344,
+ }, {
+ .tile_w = 2048,
+ .tile_h = 2048,
+ .w = 4800,
+ .h = 3344,
+ }, {
+ .tile_w = 2048,
+ .tile_h = 2048,
+ .w = 4800,
+ .h = 3344,
+ }, {
+ .tile_w = 2048,
+ .tile_h = 2048,
+ .w = 4800,
+ .h = 3344,
+ },
+};
+
+static int gsc_sw_reset(struct gsc_context *ctx)
+{
+ u32 cfg;
+ int count = GSC_RESET_TIMEOUT;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ /* s/w reset */
+ cfg = (GSC_SW_RESET_SRESET);
+ gsc_write(cfg, GSC_SW_RESET);
+
+ /* wait s/w reset complete */
+ while (count--) {
+ cfg = gsc_read(GSC_SW_RESET);
+ if (!cfg)
+ break;
+ usleep_range(1000, 2000);
+ }
+
+ if (cfg) {
+ DRM_ERROR("failed to reset gsc h/w.\n");
+ return -EBUSY;
+ }
+
+ /* display fifo reset */
+ cfg = readl(SYSREG_GSCBLK_CFG0);
+ /*
+ * GSCBLK Pixel asyncy FIFO S/W reset sequence
+ * set PXLASYNC_SW_RESET as 0 then,
+ * set PXLASYNC_SW_RESET as 1 again
+ */
+ cfg &= ~GSC_PXLASYNC_RST(ctx->id);
+ writel(cfg, SYSREG_GSCBLK_CFG0);
+ cfg |= GSC_PXLASYNC_RST(ctx->id);
+ writel(cfg, SYSREG_GSCBLK_CFG0);
+
+ /* pixel async reset */
+ cfg = readl(SYSREG_DISP1BLK_CFG);
+ /*
+ * DISPBLK1 FIFO S/W reset sequence
+ * set FIFORST_DISP1 as 0 then,
+ * set FIFORST_DISP1 as 1 again
+ */
+ cfg &= ~FIFORST_DISP1;
+ writel(cfg, SYSREG_DISP1BLK_CFG);
+ cfg |= FIFORST_DISP1;
+ writel(cfg, SYSREG_DISP1BLK_CFG);
+
+ /* reset sequence */
+ cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK);
+ cfg |= (GSC_IN_BASE_ADDR_MASK |
+ GSC_IN_BASE_ADDR_PINGPONG(0));
+ gsc_write(cfg, GSC_IN_BASE_ADDR_Y_MASK);
+ gsc_write(cfg, GSC_IN_BASE_ADDR_CB_MASK);
+ gsc_write(cfg, GSC_IN_BASE_ADDR_CR_MASK);
+
+ cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK);
+ cfg |= (GSC_OUT_BASE_ADDR_MASK |
+ GSC_OUT_BASE_ADDR_PINGPONG(0));
+ gsc_write(cfg, GSC_OUT_BASE_ADDR_Y_MASK);
+ gsc_write(cfg, GSC_OUT_BASE_ADDR_CB_MASK);
+ gsc_write(cfg, GSC_OUT_BASE_ADDR_CR_MASK);
+
+ return 0;
+}
+
+static void gsc_set_gscblk_fimd_wb(struct gsc_context *ctx, bool enable)
+{
+ u32 gscblk_cfg;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ gscblk_cfg = readl(SYSREG_GSCBLK_CFG1);
+
+ if (enable)
+ gscblk_cfg |= GSC_BLK_DISP1WB_DEST(ctx->id) |
+ GSC_BLK_GSCL_WB_IN_SRC_SEL(ctx->id) |
+ GSC_BLK_SW_RESET_WB_DEST(ctx->id);
+ else
+ gscblk_cfg |= GSC_BLK_PXLASYNC_LO_MASK_WB(ctx->id);
+
+ writel(gscblk_cfg, SYSREG_GSCBLK_CFG1);
+}
+
+static void gsc_handle_irq(struct gsc_context *ctx, bool enable,
+ bool overflow, bool done)
+{
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__,
+ enable, overflow, done);
+
+ cfg = gsc_read(GSC_IRQ);
+ cfg |= (GSC_IRQ_OR_MASK | GSC_IRQ_FRMDONE_MASK);
+
+ if (enable) {
+ cfg |= GSC_IRQ_ENABLE;
+ if (overflow)
+ cfg &= ~GSC_IRQ_OR_MASK;
+ if (done)
+ cfg &= ~GSC_IRQ_FRMDONE_MASK;
+ } else
+ cfg &= ~GSC_IRQ_ENABLE;
+
+ gsc_write(cfg, GSC_IRQ);
+}
+
+static int gsc_set_planar_addr(struct drm_exynos_ipp_buf_info *buf_info,
+ u32 fmt, struct drm_exynos_sz *sz)
+{
+ dma_addr_t *y_addr = &buf_info->base[EXYNOS_DRM_PLANAR_Y];
+ dma_addr_t *cb_addr = &buf_info->base[EXYNOS_DRM_PLANAR_CB];
+ dma_addr_t *cr_addr = &buf_info->base[EXYNOS_DRM_PLANAR_CR];
+ uint64_t y_ofs, cb_ofs, cr_ofs;
+
+ /*
+ * ToDo: check the buffer size between gem allocated buffers
+ * and each planar size.
+ */
+ switch (fmt) {
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV61:
+ y_ofs = sz->hsize * sz->vsize;
+ cb_ofs = y_ofs >> 1;
+ cr_ofs = 0;
+ break;
+ case DRM_FORMAT_NV12M:
+ y_ofs = ALIGN(ALIGN(sz->hsize, 16) *
+ ALIGN(sz->vsize, 16), SZ_2K);
+ cb_ofs = ALIGN(ALIGN(sz->hsize, 16) *
+ ALIGN(sz->vsize >> 1, 16), SZ_2K);
+ cr_ofs = 0;
+ break;
+ case DRM_FORMAT_NV12MT:
+ y_ofs = ALIGN(ALIGN(sz->hsize, 128) *
+ ALIGN(sz->vsize, 32), SZ_8K);
+ cb_ofs = ALIGN(ALIGN(sz->hsize, 128) *
+ ALIGN(sz->vsize >> 1, 32), SZ_8K);
+ cr_ofs = 0;
+ break;
+ case DRM_FORMAT_YUV410:
+ case DRM_FORMAT_YVU410:
+ case DRM_FORMAT_YUV411:
+ case DRM_FORMAT_YVU411:
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_YUV422:
+ case DRM_FORMAT_YVU422:
+ case DRM_FORMAT_YUV444:
+ case DRM_FORMAT_YVU444:
+ case DRM_FORMAT_YUV420M:
+ y_ofs = sz->hsize * sz->vsize;
+ cb_ofs = cr_ofs = y_ofs >> 2;
+ break;
+ default:
+ y_ofs = cb_ofs = cr_ofs = 0;
+ break;
+ }
+
+ if (y_ofs && *y_addr) {
+ *cb_addr = *y_addr + y_ofs;
+
+ if (cb_ofs && *cb_addr)
+ *cr_addr = *cb_addr + cb_ofs;
+ }
+
+ return 0;
+}
+
+static int gsc_src_set_fmt(struct device *dev, u32 fmt)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+
+ cfg = gsc_read(GSC_IN_CON);
+ cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |
+ GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK |
+ GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);
+
+ switch (fmt) {
+ case DRM_FORMAT_RGB565:
+ cfg |= GSC_IN_RGB565;
+ break;
+ case DRM_FORMAT_XRGB8888:
+ cfg |= GSC_IN_XRGB8888;
+ break;
+ case DRM_FORMAT_YUYV:
+ cfg |= (GSC_IN_YUV422_1P |
+ GSC_IN_YUV422_1P_ORDER_LSB_Y |
+ GSC_IN_CHROMA_ORDER_CBCR);
+ break;
+ case DRM_FORMAT_YVYU:
+ cfg |= (GSC_IN_YUV422_1P |
+ GSC_IN_YUV422_1P_ORDER_LSB_Y |
+ GSC_IN_CHROMA_ORDER_CRCB);
+ break;
+ case DRM_FORMAT_UYVY:
+ cfg |= (GSC_IN_YUV422_1P |
+ GSC_IN_YUV422_1P_OEDER_LSB_C |
+ GSC_IN_CHROMA_ORDER_CBCR);
+ break;
+ case DRM_FORMAT_VYUY:
+ cfg |= (GSC_IN_YUV422_1P |
+ GSC_IN_YUV422_1P_OEDER_LSB_C |
+ GSC_IN_CHROMA_ORDER_CRCB);
+ break;
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV61:
+ cfg |= (GSC_IN_CHROMA_ORDER_CRCB |
+ GSC_IN_YUV420_2P);
+ break;
+ case DRM_FORMAT_YUV422:
+ cfg |= GSC_IN_YUV422_3P;
+ break;
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ cfg |= GSC_IN_YUV420_3P;
+ break;
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV12M:
+ case DRM_FORMAT_NV16:
+ cfg |= (GSC_IN_CHROMA_ORDER_CBCR |
+ GSC_IN_YUV420_2P);
+ break;
+ case DRM_FORMAT_NV12MT:
+ cfg |= (GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE);
+ break;
+ default:
+ dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
+ return -EINVAL;
+ }
+
+ gsc_write(cfg, GSC_IN_CON);
+
+ return 0;
+}
+
+static int gsc_src_set_transf(struct device *dev,
+ enum drm_exynos_degree degree,
+ enum drm_exynos_flip flip)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
+ degree, flip);
+
+ cfg = gsc_read(GSC_IN_CON);
+ cfg &= ~GSC_IN_ROT_MASK;
+
+ switch (degree) {
+ case EXYNOS_DRM_DEGREE_0:
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg |= GSC_IN_ROT_XFLIP;
+ if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg |= GSC_IN_ROT_YFLIP;
+ break;
+ case EXYNOS_DRM_DEGREE_90:
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg |= GSC_IN_ROT_90_XFLIP;
+ else if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg |= GSC_IN_ROT_90_YFLIP;
+ else
+ cfg |= GSC_IN_ROT_90;
+ break;
+ case EXYNOS_DRM_DEGREE_180:
+ cfg |= GSC_IN_ROT_180;
+ break;
+ case EXYNOS_DRM_DEGREE_270:
+ cfg |= GSC_IN_ROT_270;
+ break;
+ default:
+ dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
+ return -EINVAL;
+ }
+
+ gsc_write(cfg, GSC_IN_CON);
+
+ return cfg ? 1 : 0;
+}
+
+static int gsc_src_set_size(struct device *dev, int swap,
+ struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ struct drm_exynos_ipp_property *property = ippdrv->property;
+ struct drm_exynos_ipp_config *config =
+ &property->config[EXYNOS_DRM_OPS_SRC];
+ struct drm_exynos_pos img_pos = *pos;
+ struct drm_exynos_sz img_sz = *sz;
+ u32 cfg;
+
+ /* ToDo: check width and height */
+ if (swap) {
+ img_pos.w = pos->h;
+ img_pos.h = pos->w;
+ img_sz.hsize = sz->vsize;
+ img_sz.vsize = sz->hsize;
+ }
+
+ DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n",
+ __func__, pos->x, pos->y, pos->w, pos->h);
+
+ /* pixel offset */
+ cfg = (GSC_SRCIMG_OFFSET_X(img_pos.x) |
+ GSC_SRCIMG_OFFSET_Y(img_pos.y));
+ gsc_write(cfg, GSC_SRCIMG_OFFSET);
+
+ /* cropped size */
+ cfg = (GSC_CROPPED_WIDTH(img_pos.w) |
+ GSC_CROPPED_HEIGHT(img_pos.h));
+ gsc_write(cfg, GSC_CROPPED_SIZE);
+
+ DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
+ __func__, swap, sz->hsize, sz->vsize);
+
+ /* original size */
+ cfg = gsc_read(GSC_SRCIMG_SIZE);
+ cfg &= ~(GSC_SRCIMG_HEIGHT_MASK |
+ GSC_SRCIMG_WIDTH_MASK);
+
+ cfg |= (GSC_SRCIMG_WIDTH(sz->hsize) |
+ GSC_SRCIMG_HEIGHT(sz->vsize));
+
+ gsc_write(cfg, GSC_SRCIMG_SIZE);
+
+ config->sz = img_sz;
+ config->pos = img_pos;
+
+ return 0;
+}
+
+static int gsc_src_set_buf_seq(struct gsc_context *ctx, u32 buf_id,
+ enum drm_exynos_ipp_buf_ctrl buf_ctrl)
+{
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ bool masked;
+ u32 cfg;
+ u32 mask = 0x00000001 << buf_id;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__,
+ buf_id, buf_ctrl);
+
+ /* mask register set */
+ cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK);
+
+ switch (buf_ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ masked = false;
+ break;
+ case IPP_BUF_CTRL_DEQUEUE:
+ masked = true;
+ break;
+ default:
+ dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n");
+ return -EINVAL;
+ }
+
+ /* sequence id */
+ cfg &= (~mask);
+ cfg |= masked << buf_id;
+ gsc_write(cfg, GSC_IN_BASE_ADDR_Y_MASK);
+ gsc_write(cfg, GSC_IN_BASE_ADDR_CB_MASK);
+ gsc_write(cfg, GSC_IN_BASE_ADDR_CR_MASK);
+
+ return 0;
+}
+
+static int gsc_src_set_addr(struct device *dev,
+ struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
+ enum drm_exynos_ipp_buf_ctrl buf_ctrl)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ struct drm_exynos_ipp_property *property = ippdrv->property;
+ struct drm_exynos_ipp_config *config =
+ &property->config[EXYNOS_DRM_OPS_SRC];
+ int ret;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__,
+ buf_id, buf_ctrl);
+
+ if (buf_id > GSC_MAX_SRC) {
+ dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
+ return -ENOMEM;
+ }
+
+ /* address register set */
+ switch (buf_ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ case IPP_BUF_CTRL_DEQUEUE:
+ ret = gsc_set_planar_addr(buf_info, config->fmt, &config->sz);
+
+ if (ret) {
+ dev_err(dev, "failed to set plane addr.\n");
+ return ret;
+ }
+
+ gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
+ GSC_IN_BASE_ADDR_Y(buf_id));
+ gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
+ GSC_IN_BASE_ADDR_CB(buf_id));
+ gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
+ GSC_IN_BASE_ADDR_CR(buf_id));
+ break;
+ default:
+ /* bypass */
+ break;
+ }
+
+ return gsc_src_set_buf_seq(ctx, buf_id, buf_ctrl);
+}
+
+static struct exynos_drm_ipp_ops gsc_src_ops = {
+ .set_fmt = gsc_src_set_fmt,
+ .set_transf = gsc_src_set_transf,
+ .set_size = gsc_src_set_size,
+ .set_addr = gsc_src_set_addr,
+};
+
+static int gsc_dst_set_fmt(struct device *dev, u32 fmt)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+
+ cfg = gsc_read(GSC_OUT_CON);
+ cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |
+ GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK |
+ GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);
+
+ switch (fmt) {
+ case DRM_FORMAT_RGB565:
+ cfg |= GSC_OUT_RGB565;
+ break;
+ case DRM_FORMAT_XRGB8888:
+ cfg |= GSC_OUT_XRGB8888;
+ break;
+ case DRM_FORMAT_YUYV:
+ cfg |= (GSC_OUT_YUV422_1P |
+ GSC_OUT_YUV422_1P_ORDER_LSB_Y |
+ GSC_OUT_CHROMA_ORDER_CBCR);
+ break;
+ case DRM_FORMAT_YVYU:
+ cfg |= (GSC_OUT_YUV422_1P |
+ GSC_OUT_YUV422_1P_ORDER_LSB_Y |
+ GSC_OUT_CHROMA_ORDER_CRCB);
+ break;
+ case DRM_FORMAT_UYVY:
+ cfg |= (GSC_OUT_YUV422_1P |
+ GSC_OUT_YUV422_1P_OEDER_LSB_C |
+ GSC_OUT_CHROMA_ORDER_CBCR);
+ break;
+ case DRM_FORMAT_VYUY:
+ cfg |= (GSC_OUT_YUV422_1P |
+ GSC_OUT_YUV422_1P_OEDER_LSB_C |
+ GSC_OUT_CHROMA_ORDER_CRCB);
+ break;
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV61:
+ cfg |= (GSC_OUT_CHROMA_ORDER_CRCB |
+ GSC_OUT_YUV420_2P);
+ break;
+ case DRM_FORMAT_YUV422:
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ cfg |= GSC_OUT_YUV420_3P;
+ break;
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV12M:
+ case DRM_FORMAT_NV16:
+ cfg |= (GSC_OUT_CHROMA_ORDER_CBCR |
+ GSC_OUT_YUV420_2P);
+ break;
+ case DRM_FORMAT_NV12MT:
+ cfg |= (GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE);
+ break;
+ default:
+ dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
+ return -EINVAL;
+ }
+
+ gsc_write(cfg, GSC_OUT_CON);
+
+ return 0;
+}
+
+static int gsc_dst_set_transf(struct device *dev,
+ enum drm_exynos_degree degree,
+ enum drm_exynos_flip flip)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
+ degree, flip);
+
+ cfg = gsc_read(GSC_IN_CON);
+ cfg &= ~GSC_IN_ROT_MASK;
+
+ switch (degree) {
+ case EXYNOS_DRM_DEGREE_0:
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg |= GSC_IN_ROT_XFLIP;
+ if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg |= GSC_IN_ROT_YFLIP;
+ break;
+ case EXYNOS_DRM_DEGREE_90:
+ if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+ cfg |= GSC_IN_ROT_90_XFLIP;
+ else if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+ cfg |= GSC_IN_ROT_90_YFLIP;
+ else
+ cfg |= GSC_IN_ROT_90;
+ break;
+ case EXYNOS_DRM_DEGREE_180:
+ cfg |= GSC_IN_ROT_180;
+ break;
+ case EXYNOS_DRM_DEGREE_270:
+ cfg |= GSC_IN_ROT_270;
+ break;
+ default:
+ dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
+ return -EINVAL;
+ }
+
+ gsc_write(cfg, GSC_IN_CON);
+
+ return cfg ? 1 : 0;
+}
+
+static int gsc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift)
+{
+ DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
+
+ if (src >= dst * 64) {
+ DRM_ERROR("failed to make ratio and shift.\n");
+ return -EINVAL;
+ } else if (src >= dst * 32) {
+ *ratio = 32;
+ *shift = 5;
+ } else if (src >= dst * 16) {
+ *ratio = 16;
+ *shift = 4;
+ } else if (src >= dst * 8) {
+ *ratio = 8;
+ *shift = 3;
+ } else if (src >= dst * 4) {
+ *ratio = 4;
+ *shift = 2;
+ } else if (src >= dst * 2) {
+ *ratio = 2;
+ *shift = 1;
+ } else {
+ *ratio = 1;
+ *shift = 0;
+ }
+
+ return 0;
+}
+
+static int gsc_set_prescaler(struct gsc_context *ctx, struct gsc_scaler *sc,
+ struct drm_exynos_pos *src, struct drm_exynos_pos *dst)
+{
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+ u32 hfactor, vfactor;
+ int ret = 0;
+
+ ret = gsc_get_ratio_shift(src->w, dst->w, &sc->pre_hratio, &hfactor);
+ if (ret) {
+ dev_err(ippdrv->dev, "failed to get ratio horizontal.\n");
+ return ret;
+ }
+
+ ret = gsc_get_ratio_shift(src->h, dst->h, &sc->pre_vratio, &vfactor);
+ if (ret) {
+ dev_err(ippdrv->dev, "failed to get ratio vertical.\n");
+ return ret;
+ }
+
+ DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
+ __func__, sc->pre_hratio, hfactor, sc->pre_vratio, vfactor);
+
+ sc->main_hratio = (src->w << 16) / (dst->w << hfactor);
+ sc->main_vratio = (src->h << 16) / (dst->h << vfactor);
+ DRM_DEBUG_KMS("%s:main_hratio[%ld]main_vratio[%ld]\n",
+ __func__, sc->main_hratio, sc->main_vratio);
+
+ sc->pre_shfactor = 10 - (hfactor + vfactor);
+ DRM_DEBUG_KMS("%s:pre_shfactor[%d]\n", __func__,
+ sc->pre_shfactor);
+
+ cfg = (GSC_PRESC_SHFACTOR(sc->pre_shfactor) |
+ GSC_PRESC_H_RATIO(sc->pre_hratio) |
+ GSC_PRESC_V_RATIO(sc->pre_vratio));
+ gsc_write(cfg, GSC_PRE_SCALE_RATIO);
+
+ return ret;
+}
+
+static void gsc_set_scaler(struct gsc_context *ctx, struct gsc_scaler *sc)
+{
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:main_hratio[%ld]main_vratio[%ld]\n",
+ __func__, sc->main_hratio, sc->main_vratio);
+
+ cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);
+ gsc_write(cfg, GSC_MAIN_H_RATIO);
+
+ cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio);
+ gsc_write(cfg, GSC_MAIN_V_RATIO);
+}
+
+static int gsc_dst_set_size(struct device *dev, int swap,
+ struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct drm_exynos_pos img_pos = *pos;
+ struct drm_exynos_sz img_sz = *sz;
+ struct gsc_scaler *sc = &ctx->sc;
+ u32 cfg;
+
+ DRM_DEBUG_KMS("%s:swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
+ __func__, swap, pos->x, pos->y, pos->w, pos->h);
+
+ if (swap) {
+ img_pos.w = pos->h;
+ img_pos.h = pos->w;
+ img_sz.hsize = sz->vsize;
+ img_sz.vsize = sz->hsize;
+ }
+
+ /* pixel offset */
+ cfg = (GSC_DSTIMG_OFFSET_X(img_pos.x) |
+ GSC_DSTIMG_OFFSET_Y(img_pos.y));
+ gsc_write(cfg, GSC_DSTIMG_OFFSET);
+
+ /* scaled size */
+ cfg = (GSC_SCALED_WIDTH(pos->w) | GSC_SCALED_HEIGHT(pos->h));
+ gsc_write(cfg, GSC_SCALED_SIZE);
+
+ DRM_DEBUG_KMS("%s:hsize[%d]vsize[%d]\n",
+ __func__, sz->hsize, sz->vsize);
+
+ /* original size */
+ cfg = gsc_read(GSC_DSTIMG_SIZE);
+ cfg &= ~(GSC_DSTIMG_HEIGHT_MASK |
+ GSC_DSTIMG_WIDTH_MASK);
+ cfg |= (GSC_DSTIMG_WIDTH(img_sz.hsize) |
+ GSC_DSTIMG_HEIGHT(img_sz.vsize));
+ gsc_write(cfg, GSC_DSTIMG_SIZE);
+
+ cfg = gsc_read(GSC_OUT_CON);
+ cfg &= ~GSC_OUT_RGB_TYPE_MASK;
+
+ if (pos->w >= GSC_WIDTH_ITU_709)
+ if (sc->range)
+ cfg |= GSC_OUT_RGB_HD_WIDE;
+ else
+ cfg |= GSC_OUT_RGB_HD_NARROW;
+ else
+ if (sc->range)
+ cfg |= GSC_OUT_RGB_SD_WIDE;
+ else
+ cfg |= GSC_OUT_RGB_SD_NARROW;
+
+ gsc_write(cfg, GSC_OUT_CON);
+
+ return 0;
+}
+
+static int gsc_dst_get_buf_seq(struct gsc_context *ctx)
+{
+ u32 cfg, i, buf_num = GSC_REG_SZ;
+ u32 mask = 0x00000001;
+
+ cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK);
+
+ for (i = 0; i < GSC_REG_SZ; i++)
+ if (cfg & (mask << i))
+ buf_num--;
+
+ DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
+
+ return buf_num;
+}
+
+static int gsc_dst_set_buf_seq(struct gsc_context *ctx, u32 buf_id,
+ enum drm_exynos_ipp_buf_ctrl buf_ctrl)
+{
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ bool masked;
+ u32 cfg;
+ u32 mask = 0x00000001 << buf_id;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__,
+ buf_id, buf_ctrl);
+
+ /* mask register set */
+ cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK);
+
+ switch (buf_ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ masked = false;
+ break;
+ case IPP_BUF_CTRL_DEQUEUE:
+ masked = true;
+ break;
+ default:
+ dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n");
+ return -EINVAL;
+ }
+
+ /* sequence id */
+ cfg &= (~mask);
+ cfg |= masked << buf_id;
+ gsc_write(cfg, GSC_OUT_BASE_ADDR_Y_MASK);
+ gsc_write(cfg, GSC_OUT_BASE_ADDR_CB_MASK);
+ gsc_write(cfg, GSC_OUT_BASE_ADDR_CR_MASK);
+
+ /* interrupt enable */
+ if (buf_ctrl == IPP_BUF_CTRL_QUEUE &&
+ gsc_dst_get_buf_seq(ctx) >= GSC_BUF_START)
+ gsc_handle_irq(ctx, true, false, true);
+
+ return 0;
+}
+
+static int gsc_dst_set_addr(struct device *dev,
+ struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
+ enum drm_exynos_ipp_buf_ctrl buf_ctrl)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ struct drm_exynos_ipp_property *property = ippdrv->property;
+ struct drm_exynos_ipp_config *config =
+ &property->config[EXYNOS_DRM_OPS_DST];
+ int ret;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__,
+ buf_id, buf_ctrl);
+
+ if (buf_id > GSC_MAX_DST) {
+ dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
+ return -ENOMEM;
+ }
+
+ /* address register set */
+ switch (buf_ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ case IPP_BUF_CTRL_DEQUEUE:
+ ret = gsc_set_planar_addr(buf_info, config->fmt, &config->sz);
+
+ if (ret) {
+ dev_err(dev, "failed to set plane addr.\n");
+ return ret;
+ }
+
+ gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
+ GSC_OUT_BASE_ADDR_Y(buf_id));
+ gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
+ GSC_OUT_BASE_ADDR_CB(buf_id));
+ gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
+ GSC_OUT_BASE_ADDR_CR(buf_id));
+ break;
+ default:
+ /* bypass */
+ break;
+ }
+
+ return gsc_dst_set_buf_seq(ctx, buf_id, buf_ctrl);
+}
+
+static struct exynos_drm_ipp_ops gsc_dst_ops = {
+ .set_fmt = gsc_dst_set_fmt,
+ .set_transf = gsc_dst_set_transf,
+ .set_size = gsc_dst_set_size,
+ .set_addr = gsc_dst_set_addr,
+};
+
+static int gsc_power_on(struct gsc_context *ctx, bool enable)
+{
+ DRM_DEBUG_KMS("%s:\n", __func__);
+
+ if (enable) {
+ clk_enable(ctx->gsc_clk);
+ /* ToDo : wb_b_clk */
+ ctx->suspended = false;
+ } else {
+ clk_disable(ctx->gsc_clk);
+ /* ToDo : wb_b_clk */
+ ctx->suspended = true;
+ }
+
+ return 0;
+}
+
+static irqreturn_t gsc_irq_handler(int irq, void *dev_id)
+{
+ struct gsc_context *ctx = dev_id;
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg, status;
+ int buf_id = 0;
+
+ DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id);
+
+ status = gsc_read(GSC_IRQ);
+ if (status & GSC_IRQ_STATUS_OR_IRQ) {
+ dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n",
+ ctx->id, status);
+ return IRQ_NONE;
+ }
+
+ if (status & GSC_IRQ_STATUS_OR_FRM_DONE) {
+ dev_err(ippdrv->dev, "occured frame done at %d, status 0x%x.\n",
+ ctx->id, status);
+ /* ToDo: Frame control */
+ }
+
+ if (list_empty(&ippdrv->event_list)) {
+ DRM_DEBUG_KMS("%s:event list empty.\n", __func__);
+
+ return IRQ_HANDLED;
+ }
+
+ cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK);
+ buf_id = GSC_IN_CURR_GET_INDEX(cfg);
+ if (buf_id < 0)
+ return IRQ_HANDLED;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
+
+ if (gsc_dst_set_buf_seq(ctx, buf_id,
+ IPP_BUF_CTRL_DEQUEUE) < 0) {
+ DRM_ERROR("failed to dequeue.\n");
+
+ return IRQ_HANDLED;
+ }
+
+ ipp_send_event_handler(ippdrv, buf_id);
+
+ if (gsc_dst_get_buf_seq(ctx) <= GSC_BUF_STOP)
+ gsc_handle_irq(ctx, false, false, true);
+
+ return IRQ_HANDLED;
+}
+
+static int gsc_ippdrv_check_property(struct device *dev,
+ struct drm_exynos_ipp_property *property)
+{
+ /* ToDo: check valid using property information */
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ return 0;
+}
+
+static int gsc_ippdrv_reset(struct device *dev)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ int ret;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ /* reset h/w block */
+ ret = gsc_sw_reset(ctx);
+ if (ret < 0) {
+ dev_err(dev, "failed to reset hardware.\n");
+ return ret;
+ }
+
+ memset(&ctx->sc, 0x0, sizeof(ctx->sc));
+
+ return 0;
+}
+
+static int gsc_check_prepare(struct gsc_context *ctx)
+{
+ /* ToDo: check prepare using read register */
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ return 0;
+}
+
+static int gsc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ struct drm_exynos_ipp_property *property = ippdrv->property;
+ struct drm_exynos_ipp_config *config =
+ &property->config[EXYNOS_DRM_OPS_DST];
+ u32 cfg;
+ int ret;
+ int enable = 1;
+
+ DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
+
+ ret = gsc_check_prepare(ctx);
+ if (ret) {
+ dev_err(dev, "failed to check prepare.\n");
+ return ret;
+ }
+
+ ippdrv->cmd = cmd;
+ gsc_handle_irq(ctx, true, false, true);
+
+ switch (cmd) {
+ case IPP_CMD_M2M:
+ /* bypass */
+ break;
+ case IPP_CMD_WB:
+ gsc_set_gscblk_fimd_wb(ctx, enable);
+ exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)enable);
+ break;
+ case IPP_CMD_OUTPUT:
+ default:
+ ret = -EINVAL;
+ dev_err(dev, "invalid operations.\n");
+ return ret;
+ }
+
+ ret = gsc_set_prescaler(ctx, &ctx->sc, &config->pos,
+ &config->pos);
+ if (ret) {
+ dev_err(dev, "failed to set precalser.\n");
+ return ret;
+ }
+
+ gsc_set_scaler(ctx, &ctx->sc);
+
+ cfg = gsc_read(GSC_ENABLE);
+ cfg |= GSC_ENABLE_ON;
+ gsc_write(cfg, GSC_ENABLE);
+
+ return 0;
+}
+
+static void gsc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+ u32 cfg;
+ int enable = 0;
+
+ DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
+
+ switch (cmd) {
+ case IPP_CMD_M2M:
+ /* bypass */
+ break;
+ case IPP_CMD_WB:
+ gsc_set_gscblk_fimd_wb(ctx, enable);
+ exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)enable);
+ break;
+ case IPP_CMD_OUTPUT:
+ default:
+ dev_err(dev, "invalid operations.\n");
+ break;
+ }
+
+ ippdrv->cmd = IPP_CMD_NONE;
+ gsc_handle_irq(ctx, false, false, true);
+
+ /* reset sequence */
+ gsc_write(0xff, GSC_OUT_BASE_ADDR_Y_MASK);
+ gsc_write(0xff, GSC_OUT_BASE_ADDR_CB_MASK);
+ gsc_write(0xff, GSC_OUT_BASE_ADDR_CR_MASK);
+
+ cfg = gsc_read(GSC_ENABLE);
+ cfg &= ~GSC_ENABLE_ON;
+ gsc_write(cfg, GSC_ENABLE);
+}
+
+#ifdef CONFIG_SLP_DISP_DEBUG
+static int gsc_read_reg(struct gsc_context *ctx, char *buf)
+{
+ u32 cfg;
+ int i;
+ int pos = 0;
+
+ pos += sprintf(buf+pos, "0x%.8x | ", GSC_BASE_REG(ctx->id));
+ for (i = 1; i < GSC_MAX_REG + 1; i++) {
+ cfg = gsc_read((i-1) * sizeof(u32));
+ pos += sprintf(buf+pos, "0x%.8x ", cfg);
+ if (i % 4 == 0)
+ pos += sprintf(buf+pos, "\n0x%.8x | ",
+ GSC_BASE_REG(ctx->id) + (i * sizeof(u32)));
+ }
+
+ pos += sprintf(buf+pos, "\n");
+
+ return pos;
+}
+
+static ssize_t show_read_reg(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+
+ if (!ctx->regs) {
+ dev_err(dev, "failed to get current register.\n");
+ return -EINVAL;
+ }
+
+ return gsc_read_reg(ctx, buf);
+}
+
+static struct device_attribute device_attrs[] = {
+ __ATTR(read_reg, S_IRUGO, show_read_reg, NULL),
+};
+#endif
+
+static int __devinit gsc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct gsc_context *ctx;
+ struct resource *res;
+ struct exynos_drm_ippdrv *ippdrv;
+ struct exynos_drm_gsc_pdata *pdata;
+ int ret = -EINVAL;
+#ifdef CONFIG_SLP_DISP_DEBUG
+ int i;
+#endif
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(dev, "no platform data specified.\n");
+ return -EINVAL;
+ }
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ /* clock control */
+ ctx->gsc_clk = clk_get(dev, "gscl");
+ if (IS_ERR(ctx->gsc_clk)) {
+ dev_err(dev, "failed to get gsc clock.\n");
+ ret = PTR_ERR(ctx->gsc_clk);
+ goto err_ctx;
+ }
+
+ /* resource memory */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "failed to find registers.\n");
+ ret = -ENOENT;
+ goto err_clk;
+ }
+
+ ctx->regs_res = request_mem_region(res->start, resource_size(res),
+ dev_name(dev));
+ if (!ctx->regs_res) {
+ dev_err(dev, "failed to claim register region.\n");
+ ret = -ENOENT;
+ goto err_clk;
+ }
+
+ ctx->regs = ioremap(res->start, resource_size(res));
+ if (!ctx->regs) {
+ dev_err(dev, "failed to map registers.\n");
+ ret = -ENXIO;
+ goto err_req_region;
+ }
+
+ /* resource irq */
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(dev, "failed to request irq resource.\n");
+ goto err_get_regs;
+ }
+
+ ctx->irq = res->start;
+ ret = request_threaded_irq(ctx->irq, NULL, gsc_irq_handler,
+ IRQF_ONESHOT, "drm_gsc", ctx);
+ if (ret < 0) {
+ dev_err(dev, "failed to request irq.\n");
+ goto err_get_regs;
+ }
+
+ /* context initailization */
+ ctx->id = pdev->id;
+ ctx->capa = gsc51_capa;
+ if (!ctx->capa) {
+ dev_err(dev, "failed to get capability.\n");
+ goto err_get_irq;
+ }
+
+#ifdef CONFIG_SLP_DISP_DEBUG
+ for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+ ret = device_create_file(&(pdev->dev),
+ &device_attrs[i]);
+ if (ret)
+ break;
+ }
+
+ if (ret < 0)
+ dev_err(&pdev->dev, "failed to add sysfs entries\n");
+#endif
+
+ DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+
+ ippdrv = &ctx->ippdrv;
+ ippdrv->dev = dev;
+ ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &gsc_src_ops;
+ ippdrv->ops[EXYNOS_DRM_OPS_DST] = &gsc_dst_ops;
+ ippdrv->check_property = gsc_ippdrv_check_property;
+ ippdrv->reset = gsc_ippdrv_reset;
+ ippdrv->start = gsc_ippdrv_start;
+ ippdrv->stop = gsc_ippdrv_stop;
+
+ mutex_init(&ctx->lock);
+ platform_set_drvdata(pdev, ctx);
+
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ ret = exynos_drm_ippdrv_register(ippdrv);
+ if (ret < 0) {
+ dev_err(dev, "failed to register drm gsc device.\n");
+ goto err_get_irq;
+ }
+
+ dev_info(&pdev->dev, "drm gsc registered successfully.\n");
+
+ return 0;
+
+err_get_irq:
+ free_irq(ctx->irq, ctx);
+err_get_regs:
+ iounmap(ctx->regs);
+err_req_region:
+ release_resource(ctx->regs_res);
+ kfree(ctx->regs_res);
+err_clk:
+ clk_put(ctx->gsc_clk);
+err_ctx:
+ kfree(ctx);
+ return ret;
+}
+
+static int __devexit gsc_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct gsc_context *ctx = get_gsc_context(dev);
+ struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
+
+ exynos_drm_ippdrv_unregister(ippdrv);
+
+ pm_runtime_set_suspended(dev);
+ pm_runtime_disable(dev);
+
+ free_irq(ctx->irq, ctx);
+ iounmap(ctx->regs);
+ release_resource(ctx->regs_res);
+ kfree(ctx->regs_res);
+
+ clk_put(ctx->gsc_clk);
+
+ kfree(ctx);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int gsc_suspend(struct device *dev)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+
+ DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+ if (pm_runtime_suspended(dev))
+ return 0;
+ /* ToDo */
+ return gsc_power_on(ctx, false);
+}
+
+static int gsc_resume(struct device *dev)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+
+ DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+ if (!pm_runtime_suspended(dev))
+ return gsc_power_on(ctx, true);
+ /* ToDo */
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int gsc_runtime_suspend(struct device *dev)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+
+ DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+ /* ToDo */
+ return gsc_power_on(ctx, false);
+}
+
+static int gsc_runtime_resume(struct device *dev)
+{
+ struct gsc_context *ctx = get_gsc_context(dev);
+
+ DRM_DEBUG_KMS("%s:id[%d]\n", __FILE__, ctx->id);
+ /* ToDo */
+ return gsc_power_on(ctx, true);
+}
+#endif
+
+static const struct dev_pm_ops gsc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(gsc_suspend, gsc_resume)
+ SET_RUNTIME_PM_OPS(gsc_runtime_suspend, gsc_runtime_resume, NULL)
+};
+
+/* ToDo: need to check use case platform_device_id */
+struct platform_driver gsc_driver = {
+ .probe = gsc_probe,
+ .remove = __devexit_p(gsc_remove),
+ .driver = {
+ .name = "exynos-drm-gsc",
+ .owner = THIS_MODULE,
+ .pm = &gsc_pm_ops,
+ },
+};
+
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_connector.h b/drivers/gpu/drm/exynos/exynos_drm_gsc.h
index 1c7b2b5..546089e 100644
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_connector.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.h
@@ -1,9 +1,8 @@
/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
* Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
+ * Eunchul Kim <chulspro.kim@samsung.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -25,10 +24,10 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef _EXYNOS_DRM_CONNECTOR_H_
-#define _EXYNOS_DRM_CONNECTOR_H_
+#ifndef _EXYNOS_DRM_GSC_H_
+#define _EXYNOS_DRM_GSC_H_
+
+/* ToDo */
-struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
- struct drm_encoder *encoder);
+#endif /* _EXYNOS_DRM_GSC_H_ */
-#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
index f2ffa68..b0a8e1c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
@@ -37,13 +37,13 @@
static DEFINE_MUTEX(iommu_mutex);
struct exynos_iommu_ops {
- int (*setup)(struct device *dev);
- void (*cleanup)(struct device *dev);
- int (*activate)(struct device *dev);
- void (*deactivate)(struct device *dev);
- dma_addr_t (*map)(struct device *dev, struct scatterlist *sg,
+ void *(*setup)(unsigned long s_iova, unsigned long size);
+ void (*cleanup)(void *in_vmm);
+ int (*activate)(void *in_vmm, struct device *dev);
+ void (*deactivate)(void *in_vmm, struct device *dev);
+ dma_addr_t (*map)(void *in_vmm, struct scatterlist *sg,
off_t offset, size_t size);
- void (*unmap)(struct device *dev, dma_addr_t iova);
+ void (*unmap)(void *in_vmm, dma_addr_t iova);
};
static const struct exynos_iommu_ops iommu_ops = {
@@ -55,74 +55,20 @@ static const struct exynos_iommu_ops iommu_ops = {
.unmap = iovmm_unmap
};
-static bool check_iommu_map_params(struct iommu_gem_map_params *params)
-{
- if (!params) {
- DRM_ERROR("params is null.\n");
- return false;
- }
-
- if (!params->dev || !params->drm_dev || !params->file) {
- DRM_ERROR("invalid params.\n");
- return false;
- }
-
- return true;
-}
-
-void exynos_drm_remove_iommu_list(struct list_head *iommu_list,
- void *gem_obj)
-{
- struct iommu_info_node *im, *t_im;
-
- list_for_each_entry_safe(im, t_im, iommu_list, list) {
- if (im->gem_obj == gem_obj) {
- list_del(&im->list);
- kfree(im);
- im = NULL;
- break;
- }
- }
-
-}
-
-dma_addr_t exynos_drm_iommu_map_gem(struct iommu_gem_map_params *params,
- struct list_head *iommu_list,
- unsigned int gem_handle,
- enum iommu_types type)
+dma_addr_t exynos_drm_iommu_map_gem(struct drm_device *drm_dev,
+ struct drm_gem_object *obj)
{
+ struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem_buf *buf;
struct sg_table *sgt;
- struct iommu_info_node *node;
- struct exynos_drm_gem_obj *obj;
- dma_addr_t dma_addr;
-
- if (!is_iommu_type_valid(type)) {
- DRM_ERROR("invalid iommu type.\n");
- return 0;
- }
-
- if (!check_iommu_map_params(params))
- return 0;
-
- /* get gem object from specific gem framework. */
- obj = exynos_drm_gem_get_obj(params->drm_dev, gem_handle,
- params->file);
- if (IS_ERR(obj))
- return 0;
+ dma_addr_t dev_addr;
mutex_lock(&iommu_mutex);
- /*
- * if this gem object had already been mapped to iommu then
- * return dma address mapped before this time.
- */
- if (obj->iommu_info.mapped & (1 << type)) {
- DRM_DEBUG_KMS("already mapped to iommu");
- mutex_unlock(&iommu_mutex);
- return obj->iommu_info.dma_addrs[type];
- }
+ exynos_gem_obj = to_exynos_gem_obj(obj);
- sgt = obj->buffer->sgt;
+ buf = exynos_gem_obj->buffer;
+ sgt = buf->sgt;
/*
* if not using iommu, just return base address to physical
@@ -132,102 +78,64 @@ dma_addr_t exynos_drm_iommu_map_gem(struct iommu_gem_map_params *params,
mutex_unlock(&iommu_mutex);
return sg_dma_address(&sgt->sgl[0]);
}
- mutex_unlock(&iommu_mutex);
/*
- * allocate device address space for this driver and then
- * map all pages contained in sg list to iommu table.
+ * if a gem buffer was already mapped with iommu table then
+ * just return dev_addr;
+ *
+ * Note: device address is unique to system globally.
*/
- dma_addr = iommu_ops.map(params->dev, sgt->sgl, (off_t)0,
- (size_t)obj->size);
- if (!dma_addr) {
+ if (buf->dev_addr) {
mutex_unlock(&iommu_mutex);
- return dma_addr;
+ return buf->dev_addr;
}
- mutex_lock(&iommu_mutex);
-
/*
- * check map flag bit and device address mapped to iommu.
- * this data would be used to avoid duplicated mapping.
- */
- obj->iommu_info.mapped |= (1 << type);
- obj->iommu_info.dma_addrs[type] = dma_addr;
- obj->iommu_info.devs[type] = params->dev;
- obj->iommu_info.iommu_lists[type] = iommu_list;
-
- params->gem_obj = obj;
-
- /*
- * this gem object is referenced by this driver so
- * the object refcount should be increased.
+ * allocate device address space for this driver and then
+ * map all pages contained in sg list to iommu table.
*/
- drm_gem_object_reference(&obj->base);
-
- node = kzalloc(sizeof(*node), GFP_KERNEL);
- if (!node) {
- DRM_ERROR("failed to allocate iommu node.\n");
- dma_addr = 0;
- goto err;
+ dev_addr = iommu_ops.map(exynos_gem_obj->vmm, sgt->sgl, (off_t)0,
+ (size_t)obj->size);
+ if (!dev_addr) {
+ mutex_unlock(&iommu_mutex);
+ return dev_addr;
}
- node->gem_obj = obj;
- node->dma_addr = dma_addr;
mutex_unlock(&iommu_mutex);
- list_add_tail(&node->list, iommu_list);
-
- return dma_addr;
-err:
- mutex_unlock(&iommu_mutex);
- iommu_ops.unmap(params->dev, dma_addr);
- return dma_addr;
+ return dev_addr;
}
-void exynos_drm_iommu_unmap_gem(struct iommu_gem_map_params *params,
- dma_addr_t dma_addr,
- enum iommu_types type)
+void exynos_drm_iommu_unmap_gem(struct drm_gem_object *obj)
{
- struct exynos_drm_gem_obj *obj;
-
- if (!iommu_ops.unmap)
- return;
+ struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem_buf *buf;
- if (!is_iommu_type_valid(type)) {
- DRM_ERROR("invalid iommu type.\n");
+ if (!iommu_ops.unmap || !obj)
return;
- }
- if (!check_iommu_map_params(params))
- return;
-
- if (!params->gem_obj)
- return;
+ exynos_gem_obj = to_exynos_gem_obj(obj);
+ buf = exynos_gem_obj->buffer;
- obj = (struct exynos_drm_gem_obj *)params->gem_obj;
+ /* workaround */
+ usleep_range(15000, 20000);
mutex_lock(&iommu_mutex);
- if (!(obj->iommu_info.mapped & (1 << type))) {
- DRM_DEBUG_KMS("not already mapped to iommu so just return\n");
+
+ if (!buf->dev_addr) {
mutex_unlock(&iommu_mutex);
+ DRM_DEBUG_KMS("not mapped with iommu table.\n");
return;
}
- /* uncheck map flag bit. */
- obj->iommu_info.mapped &= ~(1 << type);
- obj->iommu_info.dma_addrs[type] = 0;
- mutex_unlock(&iommu_mutex);
-
- iommu_ops.unmap(params->dev, dma_addr);
+ if (exynos_gem_obj->vmm)
+ iommu_ops.unmap(exynos_gem_obj->vmm, buf->dev_addr);
- /*
- * drop this gem object refcount to release allocated buffer
- * and resources.
- */
- drm_gem_object_unreference_unlocked(&obj->base);
+ buf->dev_addr = 0;
+ mutex_unlock(&iommu_mutex);
}
-dma_addr_t exynos_drm_iommu_map(struct device *dev, dma_addr_t paddr,
+dma_addr_t exynos_drm_iommu_map(void *in_vmm, dma_addr_t paddr,
size_t size)
{
struct sg_table *sgt;
@@ -244,13 +152,13 @@ dma_addr_t exynos_drm_iommu_map(struct device *dev, dma_addr_t paddr,
sgt = kzalloc(sizeof(struct sg_table) * npages, GFP_KERNEL);
if (!sgt) {
- dev_err(dev, "failed to allocate sg table.\n");
+ DRM_ERROR("failed to allocate sg table.\n");
return dma_addr;
}
ret = sg_alloc_table(sgt, npages, GFP_KERNEL);
if (ret < 0) {
- dev_err(dev, "failed to initialize sg table.\n");
+ DRM_ERROR("failed to initialize sg table.\n");
goto err;
}
@@ -270,9 +178,9 @@ dma_addr_t exynos_drm_iommu_map(struct device *dev, dma_addr_t paddr,
* allocate device address space for this driver and then
* map all pages contained in sg list to iommu table.
*/
- dma_addr = iommu_ops.map(dev, sgt->sgl, (off_t)0, (size_t)size);
+ dma_addr = iommu_ops.map(in_vmm, sgt->sgl, (off_t)0, (size_t)size);
if (!dma_addr)
- dev_err(dev, "failed to map cmdlist pool.\n");
+ DRM_ERROR("failed to map cmdlist pool.\n");
sg_free_table(sgt);
err:
@@ -283,45 +191,45 @@ err:
}
-void exynos_drm_iommu_unmap(struct device *dev, dma_addr_t dma_addr)
+void exynos_drm_iommu_unmap(void *in_vmm, dma_addr_t dma_addr)
{
if (iommu_ops.unmap)
- iommu_ops.unmap(dev, dma_addr);
+ iommu_ops.unmap(in_vmm, dma_addr);
}
-int exynos_drm_iommu_setup(struct device *dev)
+void *exynos_drm_iommu_setup(unsigned long s_iova, unsigned long size)
{
/*
* allocate device address space to this driver and add vmm object
* to s5p_iovmm_list. please know that each iommu will use
* 1GB as its own device address apace.
*
- * the device address space : 0x80000000 ~ 0xA0000000
+ * the device address space : s_iova ~ s_iova + size
*/
if (iommu_ops.setup)
- return iommu_ops.setup(dev);
+ return iommu_ops.setup(s_iova, size);
- return 0;
+ return ERR_PTR(-EINVAL);
}
-int exynos_drm_iommu_activate(struct device *dev)
+int exynos_drm_iommu_activate(void *in_vmm, struct device *dev)
{
if (iommu_ops.activate)
- return iovmm_activate(dev);
+ return iovmm_activate(in_vmm, dev);
return 0;
}
-void exynos_drm_iommu_deactivate(struct device *dev)
+void exynos_drm_iommu_deactivate(void *in_vmm, struct device *dev)
{
if (iommu_ops.deactivate)
- iommu_ops.deactivate(dev);
+ iommu_ops.deactivate(in_vmm, dev);
}
-void exynos_drm_iommu_cleanup(struct device *dev)
+void exynos_drm_iommu_cleanup(void *in_vmm)
{
if (iommu_ops.cleanup)
- iommu_ops.cleanup(dev);
+ iommu_ops.cleanup(in_vmm);
}
MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
index aa267ba..35d923d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
@@ -26,54 +26,33 @@
#ifndef _EXYNOS_DRM_IOMMU_H_
#define _EXYNOS_DRM_IOMMU_H_
-enum iommu_types {
- IOMMU_FIMD = 0,
- IOMMU_HDMI,
- IOMMU_G2D,
- IOMMU_FIMC,
- IOMMU_G3D,
- IOMMU_ROTATOR,
- IOMMU_MASK = 0x3f
+struct exynos_iommu_gem_data {
+ unsigned int gem_handle_in;
+ void *gem_obj_out;
};
-struct iommu_gem_map_params {
- struct device *dev;
- struct drm_device *drm_dev;
- struct drm_file *file;
- void *gem_obj;
-};
-
-#define is_iommu_type_valid(t) (((1 << (t)) & ~(IOMMU_MASK)) ? false : true)
-
-void exynos_drm_remove_iommu_list(struct list_head *iommu_list,
- void *gem_obj);
-
/* get all pages to gem object and map them to iommu table. */
-dma_addr_t exynos_drm_iommu_map_gem(struct iommu_gem_map_params *params,
- struct list_head *iommu_list,
- unsigned int gem_handle,
- enum iommu_types type);
+dma_addr_t exynos_drm_iommu_map_gem(struct drm_device *drm_dev,
+ struct drm_gem_object *obj);
/* unmap device address space to gem object from iommu table. */
-void exynos_drm_iommu_unmap_gem(struct iommu_gem_map_params *params,
- dma_addr_t dma_addr,
- enum iommu_types type);
+void exynos_drm_iommu_unmap_gem(struct drm_gem_object *obj);
/* map physical memory region pointed by paddr to iommu table. */
-dma_addr_t exynos_drm_iommu_map(struct device *dev, dma_addr_t paddr,
+dma_addr_t exynos_drm_iommu_map(void *in_vmm, dma_addr_t paddr,
size_t size);
-/* unmap device address space pointed by dma_addr from iommu table. */
-void exynos_drm_iommu_unmap(struct device *dev, dma_addr_t dma_addr);
+/* unmap device address space pointed by dev_addr from iommu table. */
+void exynos_drm_iommu_unmap(void *in_vmm, dma_addr_t dev_addr);
/* setup device address space for device iommu. */
-int exynos_drm_iommu_setup(struct device *dev);
+void *exynos_drm_iommu_setup(unsigned long s_iova, unsigned long size);
-int exynos_drm_iommu_activate(struct device *dev);
+int exynos_drm_iommu_activate(void *in_vmm, struct device *dev);
-void exynos_drm_iommu_deactivate(struct device *dev);
+void exynos_drm_iommu_deactivate(void *in_vmm, struct device *dev);
/* clean up allocated device address space for device iommu. */
-void exynos_drm_iommu_cleanup(struct device *dev);
+void exynos_drm_iommu_cleanup(void *in_vmm);
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
new file mode 100644
index 0000000..0293fbf
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -0,0 +1,1638 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co.Ltd
+ * Authors:
+ * Eunchul Kim <chulspro.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include "drmP.h"
+#include "drm_backlight.h"
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/cma.h>
+#include <plat/map-base.h>
+
+#include <drm/exynos_drm.h>
+#include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_iommu.h"
+#include "exynos_drm_ipp.h"
+
+/*
+ * IPP is stand for Image Post Processing and
+ * supports image scaler/rotator and input/output DMA operations.
+ * using FIMC, GSC, Rotator, so on.
+ * IPP is integration device driver of same attribute h/w
+ */
+
+#define get_ipp_context(dev) platform_get_drvdata(to_platform_device(dev))
+
+/*
+ * A structure of event.
+ *
+ * @base: base of event.
+ * @event: ipp event.
+ */
+struct drm_exynos_ipp_send_event {
+ struct drm_pending_event base;
+ struct drm_exynos_ipp_event event;
+};
+
+/*
+ * A structure of command node.
+ *
+ * @list: list head to command queue information.
+ * @mem_list: list head to source,destination memory queue information.
+ * @property: property information.
+ */
+struct drm_exynos_ipp_cmd_node {
+ struct list_head list;
+ struct list_head mem_list[EXYNOS_DRM_OPS_MAX];
+ struct drm_exynos_ipp_property property;
+};
+
+/*
+ * A structure of memory node.
+ *
+ * @list: list head to memory queue information.
+ * @ops_id: id of operations.
+ * @prop_id: id of property.
+ * @buf_id: id of buffer.
+ * @buf_info: gem objects and dma address, size.
+ */
+struct drm_exynos_ipp_mem_node {
+ struct list_head list;
+ enum drm_exynos_ops_id ops_id;
+ u32 prop_id;
+ u32 buf_id;
+ struct drm_exynos_ipp_buf_info buf_info;
+};
+
+/*
+ * A structure of ipp context.
+ *
+ * @subdrv: prepare initialization using subdrv.
+ * @lock: locking of operations.
+ * @ipp_idr: ipp driver idr.
+ * @sched_event: schdule event list
+ * @sched_cmd: schdule command list
+ */
+struct ipp_context {
+ struct exynos_drm_subdrv subdrv;
+ struct mutex lock;
+ struct idr ipp_idr;
+ struct work_struct sched_event;
+ struct work_struct sched_cmd;
+};
+
+static LIST_HEAD(exynos_drm_ippdrv_list);
+static BLOCKING_NOTIFIER_HEAD(exynos_drm_ippnb_list);
+
+int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
+{
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ if (!ippdrv)
+ return -EINVAL;
+
+ list_add_tail(&ippdrv->list, &exynos_drm_ippdrv_list);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_ippdrv_register);
+
+int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
+{
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ if (!ippdrv)
+ return -EINVAL;
+
+ list_del(&ippdrv->list);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_ippdrv_unregister);
+
+int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
+ struct drm_file *file)
+{
+ struct exynos_drm_ippdrv *ippdrv;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ /* get ipp driver entry */
+ list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) {
+ /* check idle state and dedicated state */
+ if (ippdrv->state == IPP_STATE_START &&
+ ippdrv->dedicated)
+ continue;
+
+ /* ToDo: get property */
+ DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, ippdrv->ipp_id);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_ipp_get_property);
+
+static int ipp_create_id(struct idr *id_idr, void *obj, u32 *idp)
+{
+ int ret = -EINVAL;
+
+ /* ToDo: need spin_lock ? */
+
+again:
+ /* ensure there is space available to allocate a handle */
+ if (idr_pre_get(id_idr, GFP_KERNEL) == 0)
+ return -ENOMEM;
+
+ ret = idr_get_new_above(id_idr, obj, 1, (int *)idp);
+ if (ret == -EAGAIN)
+ goto again;
+
+ return ret;
+}
+
+static void *ipp_find_id(struct idr *id_idr, u32 id)
+{
+ void *obj;
+
+ /* ToDo: need spin_lock ? */
+
+ /* find object using handle */
+ obj = idr_find(id_idr, id);
+ if (obj == NULL)
+ return NULL;
+
+ return obj;
+}
+
+static struct exynos_drm_ippdrv
+ *ipp_find_driver(struct ipp_context *ctx,
+ struct drm_exynos_ipp_property *property)
+{
+ struct exynos_drm_ippdrv *ippdrv;
+ u32 ipp_id = property->ipp_id;
+
+ DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, ipp_id);
+
+ if (ipp_id) {
+ /* find ipp driver */
+ ippdrv = ipp_find_id(&ctx->ipp_idr, ippdrv->ipp_id);
+ if (!ippdrv) {
+ DRM_ERROR("not found ipp%d driver.\n", ipp_id);
+ return NULL;
+ }
+
+ /* check idle state and dedicated state */
+ if (ippdrv->state == IPP_STATE_START &&
+ ippdrv->dedicated) {
+ DRM_ERROR("used choose device.\n");
+ return NULL;
+ }
+
+ /* check property */
+ if (ippdrv->check_property &&
+ ippdrv->check_property(ippdrv->dev, property)) {
+ DRM_ERROR("not support property.\n");
+ return NULL;
+ }
+
+ return ippdrv;
+ } else {
+ /* get ipp driver entry */
+ list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) {
+ /* check idle state and dedicated state */
+ if (ippdrv->state == IPP_STATE_IDLE &&
+ ippdrv->dedicated)
+ continue;
+
+ /* check property */
+ if (ippdrv->check_property &&
+ ippdrv->check_property(ippdrv->dev, property)) {
+ DRM_DEBUG_KMS("not support property.\n");
+ continue;
+ }
+
+ return ippdrv;
+ }
+
+ DRM_ERROR("not support ipp driver operations.\n");
+ }
+
+ return NULL;
+}
+
+int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_exynos_file_private *file_priv = file->driver_priv;
+ struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
+ struct device *dev = priv->dev;
+ struct ipp_context *ctx = get_ipp_context(dev);
+ struct exynos_drm_ippdrv *ippdrv;
+ struct drm_exynos_ipp_cmd_node *c_node;
+ struct drm_exynos_ipp_property *property = data;
+ int ret, i;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ if (!ctx) {
+ DRM_ERROR("invalid context.\n");
+ return -EINVAL;
+ }
+
+ if (!property) {
+ DRM_ERROR("invalid property parameter.\n");
+ return -EINVAL;
+ }
+
+ /* find ipp driver using ipp id */
+ ippdrv = ipp_find_driver(ctx, property);
+ if (!ippdrv) {
+ DRM_ERROR("failed to get ipp driver.\n");
+ return -EINVAL;
+ }
+
+ /* allocate command node */
+ c_node = kzalloc(sizeof(*c_node), GFP_KERNEL);
+ if (!c_node) {
+ DRM_ERROR("failed to allocate map node.\n");
+ return -ENOMEM;
+ }
+
+ /* create property id */
+ ret = ipp_create_id(&ippdrv->prop_idr, c_node, &property->prop_id);
+ if (ret) {
+ DRM_ERROR("failed to create id.\n");
+ goto err_clear;
+ }
+
+ DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
+
+ /* stored property information and ippdrv in private data */
+ c_node->property = *property;
+ for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++)
+ INIT_LIST_HEAD(&c_node->mem_list[i]);
+
+ /* make dedicated state without m2m */
+ if (property->cmd != IPP_CMD_M2M)
+ ippdrv->dedicated = true;
+ priv->ippdrv = ippdrv;
+
+ list_add_tail(&c_node->list, &ippdrv->cmd_list);
+
+ return 0;
+
+err_clear:
+ kfree(c_node);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_ipp_set_property);
+
+static struct drm_exynos_ipp_cmd_node
+ *ipp_find_cmd_node(struct exynos_drm_ippdrv *ippdrv, u32 prop_id)
+{
+ struct drm_exynos_ipp_cmd_node *c_node;
+
+ DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
+
+ /* ToDo: same with find_cmd_node and find_id */
+
+ /* find ipp driver */
+ c_node = ipp_find_id(&ippdrv->prop_idr, prop_id);
+ if (!c_node) {
+ DRM_ERROR("not found property%d.\n", prop_id);
+ return NULL;
+ }
+
+ return c_node;
+}
+
+static struct drm_exynos_ipp_mem_node
+ *ipp_find_mem_node(struct drm_exynos_ipp_cmd_node *c_node,
+ struct drm_exynos_ipp_buf *buf)
+{
+ struct drm_exynos_ipp_mem_node *m_node;
+ int count = 0;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf->buf_id);
+
+ /* find memory node entry */
+ list_for_each_entry(m_node, &c_node->mem_list[buf->ops_id], list) {
+ DRM_DEBUG_KMS("%s:count[%d]c_node[0x%x]\n",
+ __func__, count++, (int)c_node);
+
+ /* compare buffer id */
+ if (m_node->buf_id == buf->buf_id)
+ return m_node;
+ }
+
+ return NULL;
+}
+
+static struct drm_exynos_ipp_property
+ *ipp_find_property(struct exynos_drm_ippdrv *ippdrv, u32 prop_id)
+{
+ struct drm_exynos_ipp_property *property;
+ struct drm_exynos_ipp_cmd_node *c_node;
+ int count = 0;
+
+ DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
+
+ /* find command node entry */
+ list_for_each_entry(c_node, &ippdrv->cmd_list, list) {
+ DRM_DEBUG_KMS("%s:count[%d]c_node[0x%x]\n",
+ __func__, count++, (int)c_node);
+
+ property = &c_node->property;
+ /* compare property id */
+ if (property->prop_id == prop_id)
+ return property;
+ }
+
+ return NULL;
+}
+
+static int ipp_set_property(struct exynos_drm_ippdrv *ippdrv,
+ struct drm_exynos_ipp_property *property)
+{
+ struct exynos_drm_ipp_ops *ops = NULL;
+ int ret, i, swap = 0;
+
+ if (!property) {
+ DRM_ERROR("invalid property parameter.\n");
+ return -EINVAL;
+ }
+
+ DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
+
+ /* reset h/w block */
+ if (ippdrv->reset &&
+ ippdrv->reset(ippdrv->dev)) {
+ DRM_ERROR("failed to reset.\n");
+ return -EINVAL;
+ }
+
+ /* set source,destination operations */
+ for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) {
+ /* ToDo: integrate property and config */
+ struct drm_exynos_ipp_config *config =
+ &property->config[i];
+
+ ops = ippdrv->ops[i];
+ if (!ops || !config) {
+ DRM_ERROR("not support ops and config.\n");
+ return -EINVAL;
+ }
+
+ /* set format */
+ if (ops->set_fmt) {
+ ret = ops->set_fmt(ippdrv->dev, config->fmt);
+ if (ret) {
+ DRM_ERROR("not support format.\n");
+ return ret;
+ }
+ }
+
+ /* set transform for rotation, flip */
+ if (ops->set_transf) {
+ swap = ops->set_transf(ippdrv->dev, config->degree,
+ config->flip);
+ if (swap < 0) {
+ DRM_ERROR("not support tranf.\n");
+ return -EINVAL;
+ }
+ }
+
+ /* set size */
+ if (ops->set_size) {
+ ret = ops->set_size(ippdrv->dev, swap, &config->pos,
+ &config->sz);
+ if (ret) {
+ DRM_ERROR("not support size.\n");
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
+ struct drm_exynos_ipp_mem_node *node)
+{
+ struct exynos_drm_ipp_ops *ops = NULL;
+ int ret;
+
+ DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)node);
+
+ if (!node) {
+ DRM_ERROR("invalid queue node.\n");
+ ret = -EFAULT;
+ return ret;
+ }
+
+ DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, node->ops_id);
+
+ /* get operations callback */
+ ops = ippdrv->ops[node->ops_id];
+ if (!ops) {
+ DRM_DEBUG_KMS("not support ops.\n");
+ ret = -EIO;
+ return ret;
+ }
+
+ /* set address and enable irq */
+ if (ops->set_addr) {
+ ret = ops->set_addr(ippdrv->dev, &node->buf_info,
+ node->buf_id, IPP_BUF_CTRL_QUEUE);
+ if (ret) {
+ if (ret != -ENOMEM)
+ DRM_ERROR("failed to set addr.\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int ipp_free_mem_node(struct drm_device *drm_dev,
+ struct exynos_drm_ippdrv *ippdrv,
+ struct drm_exynos_ipp_mem_node *node)
+{
+ int ret, i;
+
+ DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)node);
+
+ if (!node) {
+ DRM_ERROR("invalid queue node.\n");
+ ret = -EFAULT;
+ return ret;
+ }
+
+ DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, node->ops_id);
+
+ /* put gem buffer */
+ for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) {
+ void *gem_obj = node->buf_info.gem_objs[i];
+
+ if (gem_obj)
+ exynos_drm_gem_put_dma_addr(drm_dev, gem_obj);
+ }
+
+ /* delete list in queue */
+ list_del(&node->list);
+ kfree(node);
+
+ return 0;
+}
+
+/* ToDo: Merge with stop property */
+static void ipp_free_cmd_list(struct drm_device *drm_dev,
+ struct exynos_drm_ippdrv *ippdrv)
+{
+ struct drm_exynos_ipp_cmd_node *c_node, *tc_node;
+ struct drm_exynos_ipp_mem_node *m_node, *tm_node;
+ struct list_head *head;
+ int ret, i, count = 0;
+
+ /* get command node entry */
+ list_for_each_entry_safe(c_node, tc_node,
+ &ippdrv->cmd_list, list) {
+ DRM_DEBUG_KMS("%s:count[%d]c_node[0x%x]\n",
+ __func__, count++, (int)c_node);
+
+ for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) {
+ /* source/destination memory list */
+ head = &c_node->mem_list[i];
+
+ /* get memory node entry */
+ list_for_each_entry_safe(m_node, tm_node, head, list) {
+ /* free memory node to ippdrv */
+ ret = ipp_free_mem_node(drm_dev, ippdrv,
+ m_node);
+ if (ret)
+ DRM_ERROR("failed to free m node.\n");
+ }
+ }
+
+ /* delete list */
+ list_del(&c_node->list);
+ kfree(c_node);
+ }
+
+ return;
+}
+
+static int ipp_start_property(struct drm_device *drm_dev,
+ struct exynos_drm_ippdrv *ippdrv, u32 prop_id)
+{
+ struct drm_exynos_ipp_cmd_node *c_node;
+ struct drm_exynos_ipp_mem_node *m_node, tm_node;
+ struct drm_exynos_ipp_property *property;
+ struct list_head *head;
+ int ret, i;
+
+ DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
+
+ /* find command node */
+ c_node = ipp_find_cmd_node(ippdrv, prop_id);
+ if (!c_node) {
+ DRM_ERROR("invalid command node list.\n");
+ return -EINVAL;
+ }
+
+ /* get property */
+ property = &c_node->property;
+ if (property->prop_id != prop_id) {
+ DRM_ERROR("invalid property id.\n");
+ return -EINVAL;
+ }
+
+ /* set current property in ippdrv */
+ ippdrv->property = property;
+ ret = ipp_set_property(ippdrv, property);
+ if (ret) {
+ DRM_ERROR("failed to set property.\n");
+ ippdrv->property = NULL;
+ return ret;
+ }
+
+ /* check command type */
+ switch (property->cmd) {
+ case IPP_CMD_M2M:
+ for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) {
+ /* source/destination memory list */
+ head = &c_node->mem_list[i];
+
+ if (list_empty(head)) {
+ DRM_DEBUG_KMS("bypass empty list.\n");
+ return 0;
+ }
+
+ /* get first entry */
+ m_node = list_first_entry(head,
+ struct drm_exynos_ipp_mem_node, list);
+ if (!m_node) {
+ DRM_DEBUG_KMS("failed to get node.\n");
+ ret = -EFAULT;
+ return ret;
+ }
+
+ DRM_DEBUG_KMS("%s:m_node[0x%x]\n",
+ __func__, (int)m_node);
+
+ /* must be set 0 src buffer id in m2m */
+ if (i == EXYNOS_DRM_OPS_SRC) {
+ tm_node = *m_node;
+ tm_node.buf_id = 0;
+ m_node = &tm_node;
+ }
+
+ /* set memory node to ippdrv */
+ ret = ipp_set_mem_node(ippdrv, m_node);
+ if (ret) {
+ DRM_ERROR("failed to set m node.\n");
+ return ret;
+ }
+ }
+ break;
+ case IPP_CMD_WB:
+ /* destination memory list */
+ head = &c_node->mem_list[EXYNOS_DRM_OPS_DST];
+
+ /* get list entry */
+ list_for_each_entry(m_node, head, list) {
+ /* set memory node to ippdrv */
+ ret = ipp_set_mem_node(ippdrv, m_node);
+ if (ret) {
+ DRM_ERROR("failed to set m node.\n");
+ return ret;
+ }
+ }
+ break;
+ case IPP_CMD_OUTPUT:
+ /* source memory list */
+ head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC];
+
+ /* get list entry */
+ list_for_each_entry(m_node, head, list) {
+ /* set memory node to ippdrv */
+ ret = ipp_set_mem_node(ippdrv, m_node);
+ if (ret) {
+ DRM_ERROR("failed to set m node.\n");
+ return ret;
+ }
+ }
+ break;
+ default:
+ DRM_ERROR("invalid operations.\n");
+ ret = -EINVAL;
+ return ret;
+ }
+
+ /* start operations */
+ if (ippdrv->start) {
+ ret = ippdrv->start(ippdrv->dev, property->cmd);
+ if (ret) {
+ DRM_ERROR("failed to start ops.\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int ipp_stop_property(struct drm_device *drm_dev,
+ struct exynos_drm_ippdrv *ippdrv, u32 prop_id)
+{
+ struct drm_exynos_ipp_cmd_node *c_node;
+ struct drm_exynos_ipp_mem_node *m_node, *tm_node;
+ struct drm_exynos_ipp_property *property;
+ enum drm_exynos_ipp_cmd cmd;
+ struct list_head *head;
+ int ret, i;
+
+ DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
+
+ /* find command node */
+ c_node = ipp_find_cmd_node(ippdrv, prop_id);
+ if (!c_node) {
+ DRM_ERROR("invalid command node list.\n");
+ return -EINVAL;
+ }
+
+ /* get property */
+ property = &c_node->property;
+ if (property->prop_id != prop_id) {
+ DRM_ERROR("invalid property id.\n");
+ return -EINVAL;
+ }
+
+ /* copy current command for memory list */
+ cmd = property->cmd;
+
+ /* stop operations */
+ if (ippdrv->stop)
+ ippdrv->stop(ippdrv->dev, property->cmd);
+
+ /* check command type */
+ switch (property->cmd) {
+ case IPP_CMD_M2M:
+ for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) {
+ /* source/destination memory list */
+ head = &c_node->mem_list[i];
+
+ /* get list entry */
+ list_for_each_entry_safe(m_node, tm_node,
+ head, list) {
+ /* free memory node to ippdrv */
+ ret = ipp_free_mem_node(drm_dev, ippdrv,
+ m_node);
+ if (ret) {
+ DRM_ERROR("failed to free m node.\n");
+ return ret;
+ }
+ }
+ }
+ break;
+ case IPP_CMD_WB:
+ /* destination memory list */
+ head = &c_node->mem_list[EXYNOS_DRM_OPS_DST];
+
+ /* get list entry */
+ list_for_each_entry_safe(m_node, tm_node, head, list) {
+ /* free memory node to ippdrv */
+ ret = ipp_free_mem_node(drm_dev, ippdrv, m_node);
+ if (ret) {
+ DRM_ERROR("failed to free m node.\n");
+ return ret;
+ }
+ }
+ break;
+ case IPP_CMD_OUTPUT:
+ /* source memory list */
+ head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC];
+
+ /* get list entry */
+ list_for_each_entry_safe(m_node, tm_node, head, list) {
+ /* free memory node to ippdrv */
+ ret = ipp_free_mem_node(drm_dev, ippdrv, m_node);
+ if (ret) {
+ DRM_ERROR("failed to free m node.\n");
+ return ret;
+ }
+ }
+ break;
+ default:
+ DRM_ERROR("invalid operations.\n");
+ ret = -EINVAL;
+ return ret;
+ }
+
+ /* delete list */
+ list_del(&c_node->list);
+ kfree(c_node);
+
+ return 0;
+}
+
+static void ipp_free_event(struct drm_pending_event *event)
+{
+ kfree(event);
+}
+
+static int ipp_make_event(struct drm_device *drm_dev, struct drm_file *file,
+ struct exynos_drm_ippdrv *ippdrv, struct drm_exynos_ipp_buf *buf)
+{
+ struct drm_exynos_ipp_send_event *e;
+ unsigned long flags;
+
+ DRM_DEBUG_KMS("%s:ops_id[%d]buf_id[%d]\n", __func__,
+ buf->ops_id, buf->buf_id);
+
+ e = kzalloc(sizeof(*e), GFP_KERNEL);
+ if (!e) {
+ DRM_ERROR("failed to allocate event.\n");
+
+ spin_lock_irqsave(&drm_dev->event_lock, flags);
+ file->event_space += sizeof(e->event);
+ spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+ return -ENOMEM;
+ }
+
+ DRM_DEBUG_KMS("%s:e[0x%x]\n", __func__, (int)e);
+
+ /* make event */
+ e->event.base.type = DRM_EXYNOS_IPP_EVENT;
+ e->event.base.length = sizeof(e->event);
+ e->event.user_data = buf->user_data;
+ e->event.buf_id[EXYNOS_DRM_OPS_DST] = buf->buf_id;
+ e->base.event = &e->event.base;
+ e->base.file_priv = file;
+ e->base.destroy = ipp_free_event;
+
+ list_add_tail(&e->base.link, &ippdrv->event_list);
+
+ return 0;
+}
+
+static struct drm_exynos_ipp_mem_node
+ *ipp_make_mem_node(struct drm_device *drm_dev,
+ struct drm_file *file,
+ struct exynos_drm_ippdrv *ippdrv,
+ struct drm_exynos_ipp_buf *buf)
+{
+ struct drm_exynos_ipp_cmd_node *c_node;
+ struct drm_exynos_ipp_mem_node *m_node;
+ struct drm_exynos_ipp_buf_info buf_info;
+ void *addr;
+ unsigned long size;
+ int i;
+
+ m_node = kzalloc(sizeof(*m_node), GFP_KERNEL);
+ if (!m_node) {
+ DRM_ERROR("failed to allocate queue node.\n");
+ return NULL;
+ }
+
+ /* clear base address for error handling */
+ memset(&buf_info, 0x0, sizeof(buf_info));
+
+ /* find command node */
+ c_node = ipp_find_cmd_node(ippdrv, buf->prop_id);
+ if (!c_node) {
+ DRM_ERROR("failed to get command node.\n");
+ goto err_clear;
+ }
+
+ /* operations, buffer id */
+ m_node->ops_id = buf->ops_id;
+ m_node->prop_id = buf->prop_id;
+ m_node->buf_id = buf->buf_id;
+
+ DRM_DEBUG_KMS("%s:m_node[0x%x]ops_id[%d]\n", __func__,
+ (int)m_node, buf->ops_id);
+ DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]\n", __func__,
+ buf->prop_id, m_node->buf_id);
+
+ for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) {
+ unsigned int gem_obj;
+
+ DRM_DEBUG_KMS("%s:i[%d]handle[0x%x]\n", __func__,
+ i, buf->handle[i]);
+
+ /* get dma address by handle */
+ if (buf->handle[i] != 0) {
+ addr = exynos_drm_gem_get_dma_addr(drm_dev,
+ buf->handle[i], file, &gem_obj);
+ if (!addr) {
+ DRM_ERROR("failed to get addr.\n");
+ goto err_clear;
+ }
+
+ size = exynos_drm_gem_get_size(drm_dev,
+ buf->handle[i], file);
+ if (!size) {
+ DRM_ERROR("failed to get size.\n");
+ goto err_clear;
+ }
+
+ buf_info.gem_objs[i] = (void *)gem_obj;
+ buf_info.base[i] = *(dma_addr_t *) addr;
+ buf_info.size[i] = (uint64_t) size;
+ }
+ }
+
+ m_node->buf_info = buf_info;
+ list_add_tail(&m_node->list, &c_node->mem_list[buf->ops_id]);
+
+ return m_node;
+
+err_clear:
+ kfree(m_node);
+
+ return NULL;
+}
+
+int exynos_drm_ipp_buf(struct drm_device *drm_dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_exynos_file_private *file_priv = file->driver_priv;
+ struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
+ struct exynos_drm_ippdrv *ippdrv = priv->ippdrv;
+ struct drm_exynos_ipp_buf *buf = data;
+ struct exynos_drm_ipp_ops *ops = NULL;
+ struct drm_exynos_ipp_send_event *e, *te;
+ struct drm_exynos_ipp_cmd_node *c_node;
+ struct drm_exynos_ipp_mem_node *m_node = NULL, *tm_node;
+ struct drm_exynos_ipp_property *property;
+ struct drm_exynos_ipp_buf_info buf_info;
+ struct list_head *head;
+ int ret, i;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ if (!buf) {
+ DRM_ERROR("invalid buf parameter.\n");
+ return -EINVAL;
+ }
+
+ if (!ippdrv) {
+ DRM_ERROR("failed to get ipp driver.\n");
+ return -EINVAL;
+ }
+
+ if (buf->ops_id >= EXYNOS_DRM_OPS_MAX) {
+ DRM_ERROR("invalid ops parameter.\n");
+ return -EINVAL;
+ }
+
+ ops = ippdrv->ops[buf->ops_id];
+ if (!ops) {
+ DRM_ERROR("failed to get ops.\n");
+ return -EINVAL;
+ }
+
+ DRM_DEBUG_KMS("%s:ops_id[%s]buf_id[%d]buf_ctrl[%d]\n",
+ __func__, buf->ops_id ? "dst" : "src",
+ buf->buf_id, buf->buf_ctrl);
+
+ /* clear base address for error handling */
+ memset(&buf_info, 0x0, sizeof(buf_info));
+
+ /* find command node */
+ c_node = ipp_find_cmd_node(ippdrv, buf->prop_id);
+ if (!c_node) {
+ DRM_ERROR("failed to get command node.\n");
+ ret = -EINVAL;
+ goto err_clear;
+ }
+
+ /* get property */
+ property = &c_node->property;
+ if (!property) {
+ DRM_ERROR("invalid property parameter.\n");
+ goto err_clear;
+ }
+
+ /* buffer control */
+ switch (buf->buf_ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ /* make memory node */
+ m_node = ipp_make_mem_node(drm_dev, file, ippdrv, buf);
+ if (!m_node) {
+ DRM_ERROR("failed to make queue node.\n");
+ ret = -EINVAL;
+ goto err_clear;
+ }
+
+ buf_info = m_node->buf_info;
+
+ if (pm_runtime_suspended(ippdrv->dev))
+ break;
+
+ /* set address */
+ if (property->cmd != IPP_CMD_M2M && ops->set_addr) {
+ ret = ops->set_addr(ippdrv->dev, &buf_info, buf->buf_id,
+ buf->buf_ctrl);
+ if (ret) {
+ DRM_ERROR("failed to set addr.\n");
+ goto err_clear;
+ }
+ }
+ break;
+ case IPP_BUF_CTRL_DEQUEUE:
+ /* free node */
+ list_for_each_entry_safe(m_node, tm_node,
+ &c_node->mem_list[buf->ops_id], list) {
+ if (m_node->buf_id == buf->buf_id &&
+ m_node->ops_id == buf->ops_id) {
+ /* free memory node to ippdrv */
+ ret = ipp_free_mem_node(drm_dev, ippdrv,
+ m_node);
+ if (ret) {
+ DRM_ERROR("failed to free m node.\n");
+ goto err_clear;
+ }
+ }
+ }
+
+ if (pm_runtime_suspended(ippdrv->dev)) {
+ DRM_ERROR("suspended:invalid operations.\n");
+ ret = -EINVAL;
+ goto err_clear;
+ }
+
+ /* clear address */
+ if (ops->set_addr) {
+ ret = ops->set_addr(ippdrv->dev, &buf_info, buf->buf_id,
+ buf->buf_ctrl);
+ if (ret) {
+ DRM_ERROR("failed to set addr.\n");
+ goto err_clear;
+ }
+ }
+ break;
+ default:
+ DRM_ERROR("invalid buffer control.\n");
+ return -EINVAL;
+ }
+
+ /* destination buffer need event control */
+ if (buf->ops_id == EXYNOS_DRM_OPS_DST) {
+ switch (buf->buf_ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ /* make event */
+ ret = ipp_make_event(drm_dev, file, ippdrv, buf);
+ if (ret) {
+ DRM_ERROR("failed to make event.\n");
+ goto err_clear;
+ }
+ break;
+ case IPP_BUF_CTRL_DEQUEUE:
+ /* free event */
+ list_for_each_entry_safe(e, te,
+ &ippdrv->event_list, base.link) {
+ if (e->event.buf_id[EXYNOS_DRM_OPS_DST] ==
+ buf->buf_id) {
+ /* delete list */
+ list_del(&e->base.link);
+ kfree(e);
+ }
+ }
+ break;
+ default:
+ /* no action */
+ break;
+ }
+ }
+
+ /*
+ * If set source, destination buffer and enable pm
+ * m2m operations need start operations in queue
+ */
+ if (property->cmd == IPP_CMD_M2M) {
+ /* start operations was not set */
+ if (pm_runtime_suspended(ippdrv->dev)) {
+ DRM_DEBUG_KMS("suspended state.\n");
+ return 0;
+ }
+
+ /* check source/destination buffer status */
+ for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) {
+ /* source/destination memory list */
+ head = &c_node->mem_list[i];
+
+ /* check list empty */
+ if (list_empty(head)) {
+ DRM_DEBUG_KMS("list empty.\n");
+ return 0;
+ }
+ }
+
+ /* check property id and buffer property id */
+ if (property->prop_id != buf->prop_id) {
+ DRM_ERROR("invalid property id.\n");
+ goto err_clear;
+ }
+
+ /* start property */
+ ret = ipp_start_property(drm_dev, ippdrv, property->prop_id);
+ if (ret) {
+ DRM_ERROR("failed to start property.\n");
+ goto err_clear;
+ }
+ }
+
+ return 0;
+
+err_clear:
+ DRM_ERROR("%s:failed to set buf.\n", __func__);
+
+ /* delete list */
+ list_for_each_entry_safe(m_node, tm_node,
+ &c_node->mem_list[buf->ops_id], list) {
+ if (m_node->buf_id == buf->buf_id &&
+ m_node->ops_id == buf->ops_id) {
+ list_del(&m_node->list);
+ kfree(m_node);
+ }
+ }
+
+ /* put gem buffer */
+ for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) {
+ void *gem_obj = buf_info.gem_objs[i];
+
+ if (gem_obj)
+ exynos_drm_gem_put_dma_addr(drm_dev,
+ gem_obj);
+ }
+
+ /* free address */
+ switch (buf->buf_ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ case IPP_BUF_CTRL_DEQUEUE:
+ if (pm_runtime_suspended(ippdrv->dev)) {
+ DRM_ERROR("suspended:invalid error operations.\n");
+ return -EINVAL;
+ }
+
+ /* clear base address for error handling */
+ memset(&buf_info, 0x0, sizeof(buf_info));
+
+ /* don't need check error case */
+ if (ops->set_addr)
+ ops->set_addr(ippdrv->dev, &buf_info,
+ buf->buf_id, IPP_BUF_CTRL_DEQUEUE);
+ break;
+ default:
+ /* no action */
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_ipp_buf);
+
+int exynos_drm_ipp_ctrl(struct drm_device *drm_dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_exynos_file_private *file_priv = file->driver_priv;
+ struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
+ struct exynos_drm_ippdrv *ippdrv = priv->ippdrv;
+ struct drm_exynos_ipp_ctrl *ctrl = data;
+ int ret;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ if (!ctrl) {
+ DRM_ERROR("invalid control parameter.\n");
+ return -EINVAL;
+ }
+
+ if (!ippdrv) {
+ DRM_ERROR("failed to get ipp driver.\n");
+ return -EINVAL;
+ }
+
+ DRM_DEBUG_KMS("%s:use[%d]\n", __func__, ctrl->use);
+
+ /* ToDo: expand ctrl operation */
+
+ /*
+ * start/stop operations,
+ * set use to 1, you can use start operations
+ * other case is stop opertions
+ */
+ if (ctrl->use) {
+ if (pm_runtime_suspended(ippdrv->dev))
+ pm_runtime_get_sync(ippdrv->dev);
+
+ ret = ipp_start_property(drm_dev, ippdrv, ctrl->prop_id);
+ if (ret) {
+ DRM_ERROR("failed to start property.\n");
+ goto err_clear;
+ }
+
+ ippdrv->state = IPP_STATE_START;
+ } else {
+ ippdrv->state = IPP_STATE_STOP;
+ ippdrv->dedicated = false;
+ ippdrv->property = NULL;
+
+ ret = ipp_stop_property(drm_dev, ippdrv, ctrl->prop_id);
+ if (ret) {
+ DRM_ERROR("failed to stop property.\n");
+ goto err_clear;
+ }
+
+ if (!pm_runtime_suspended(ippdrv->dev))
+ pm_runtime_put_sync(ippdrv->dev);
+ }
+
+ return 0;
+
+err_clear:
+ /*
+ * ToDo: register clear if needed
+ * If failed choose device using property. then
+ * revert register clearing if needed
+ */
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_ipp_ctrl);
+
+int exynos_drm_ippnb_register(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(
+ &exynos_drm_ippnb_list, nb);
+}
+EXPORT_SYMBOL_GPL(exynos_drm_ippnb_register);
+
+int exynos_drm_ippnb_unregister(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(
+ &exynos_drm_ippnb_list, nb);
+}
+EXPORT_SYMBOL_GPL(exynos_drm_ippnb_unregister);
+
+int exynos_drm_ippnb_send_event(unsigned long val, void *v)
+{
+ return blocking_notifier_call_chain(
+ &exynos_drm_ippnb_list, val, v);
+}
+EXPORT_SYMBOL_GPL(exynos_drm_ippnb_send_event);
+
+void ipp_send_event_handler(struct exynos_drm_ippdrv *ippdrv,
+ int buf_id)
+{
+ struct drm_device *drm_dev = ippdrv->drm_dev;
+ struct drm_exynos_ipp_property *property = ippdrv->property;
+ struct drm_exynos_ipp_cmd_node *c_node;
+ struct drm_exynos_ipp_mem_node *m_node;
+ struct drm_exynos_ipp_buf buf;
+ struct drm_exynos_ipp_send_event *e;
+ struct list_head *head;
+ struct timeval now;
+ unsigned long flags;
+ u32 q_buf_id[EXYNOS_DRM_OPS_MAX] = {0, };
+ int ret, i;
+
+ DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
+
+ if (!drm_dev) {
+ DRM_ERROR("failed to get drm_dev.\n");
+ return;
+ }
+
+ if (list_empty(&ippdrv->event_list)) {
+ DRM_ERROR("event list is empty.\n");
+ return;
+ }
+
+ if (!property) {
+ DRM_ERROR("failed to get property.\n");
+ return;
+ }
+
+ /* find command node */
+ c_node = ipp_find_cmd_node(ippdrv, property->prop_id);
+ if (!c_node) {
+ DRM_ERROR("invalid command node list.\n");
+ return;
+ }
+
+ /* check command type */
+ switch (property->cmd) {
+ case IPP_CMD_M2M:
+ for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) {
+ /* source/destination memory list */
+ head = &c_node->mem_list[i];
+
+ if (list_empty(head)) {
+ DRM_ERROR("empty list.\n");
+ return;
+ }
+
+ /* get first entry */
+ m_node = list_first_entry(head,
+ struct drm_exynos_ipp_mem_node, list);
+ if (!m_node) {
+ DRM_ERROR("empty list.\n");
+ return;
+ }
+
+ q_buf_id[i] = m_node->buf_id;
+
+ /* free memory node to ippdrv */
+ ret = ipp_free_mem_node(drm_dev, ippdrv, m_node);
+ if (ret)
+ DRM_ERROR("failed to free m node.\n");
+ }
+ break;
+ case IPP_CMD_WB:
+ /* clear buf for finding */
+ memset(&buf, 0x0, sizeof(buf));
+ buf.ops_id = EXYNOS_DRM_OPS_DST;
+ buf.buf_id = buf_id;
+
+ /* get memory node entry */
+ m_node = ipp_find_mem_node(c_node, &buf);
+ if (!m_node) {
+ DRM_ERROR("empty list.\n");
+ return;
+ }
+
+ q_buf_id[EXYNOS_DRM_OPS_DST] = m_node->buf_id;
+
+ /* free memory node to ippdrv */
+ ret = ipp_free_mem_node(drm_dev, ippdrv, m_node);
+ if (ret)
+ DRM_ERROR("failed to free m node.\n");
+ break;
+ case IPP_CMD_OUTPUT:
+ /* source memory list */
+ head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC];
+
+ /* get first entry */
+ m_node = list_first_entry(head,
+ struct drm_exynos_ipp_mem_node, list);
+ if (!m_node) {
+ DRM_ERROR("empty list.\n");
+ return;
+ }
+
+ q_buf_id[EXYNOS_DRM_OPS_SRC] = m_node->buf_id;
+
+ /* free memory node to ippdrv */
+ ret = ipp_free_mem_node(drm_dev, ippdrv, m_node);
+ if (ret)
+ DRM_ERROR("failed to free m node.\n");
+ break;
+ default:
+ DRM_ERROR("invalid operations.\n");
+ return;
+ }
+
+ /* ToDo: Fix buffer id */
+ if (q_buf_id[EXYNOS_DRM_OPS_DST] != buf_id)
+ DRM_ERROR("failed to match buffer id %d, %d.\n",
+ q_buf_id[EXYNOS_DRM_OPS_DST], buf_id);
+
+ /* get first event entry */
+ e = list_first_entry(&ippdrv->event_list,
+ struct drm_exynos_ipp_send_event, base.link);
+
+ do_gettimeofday(&now);
+ e->event.tv_sec = now.tv_sec;
+ e->event.tv_usec = now.tv_usec;
+ e->event.prop_id = property->prop_id;
+
+ /* set buffer id about source destination */
+ for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) {
+ /* ToDo: compare index. If needed */
+ e->event.buf_id[i] = q_buf_id[i];
+ }
+
+ spin_lock_irqsave(&drm_dev->event_lock, flags);
+ list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+ wake_up_interruptible(&e->base.file_priv->event_wait);
+ spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+
+ /* ToDo: Need to handle the property queue */
+
+ switch (property->cmd) {
+ case IPP_CMD_M2M:
+ for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) {
+ head = &c_node->mem_list[i];
+ if (list_empty(head))
+ return;
+ }
+
+ ret = ipp_start_property(drm_dev, ippdrv, property->prop_id);
+ if (ret) {
+ DRM_ERROR("failed to start property.\n");
+ return;
+ }
+ break;
+ case IPP_CMD_WB:
+ case IPP_CMD_OUTPUT:
+ default:
+ break;
+ }
+
+ DRM_DEBUG_KMS("%s:finish cmd[%d]\n", __func__, property->cmd);
+}
+
+static void ipp_sched_event(struct work_struct *sched_event)
+{
+ struct ipp_context *ctx = container_of(sched_event,
+ struct ipp_context, sched_event);
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+ /* ToDo:send event handler */
+}
+
+static void ipp_sched_cmd(struct work_struct *sched_cmd)
+{
+ struct ipp_context *ctx = container_of(sched_cmd,
+ struct ipp_context, sched_cmd);
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+ /* ToDo: schedule next work */
+}
+
+static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
+{
+ struct exynos_drm_ippdrv *ippdrv;
+ struct exynos_drm_private *drm_priv = drm_dev->dev_private;
+ int ret;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ /* get ipp driver entry */
+ list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) {
+ ippdrv->drm_dev = drm_dev;
+
+ /* ToDo: need move open ? */
+
+ /* init prop idr */
+ idr_init(&ippdrv->prop_idr);
+
+ /* check iommu use case */
+ if (ippdrv->iommu_used) {
+ ret = exynos_drm_iommu_activate(drm_priv->vmm,
+ ippdrv->dev);
+ if (ret) {
+ DRM_ERROR("failed to activate iommu\n");
+ goto err_clear;
+ }
+ }
+ }
+
+ return 0;
+
+err_clear:
+ /* get ipp driver entry */
+ list_for_each_entry_reverse(ippdrv, &exynos_drm_ippdrv_list, list)
+ if ((ippdrv->iommu_used) && (drm_priv->vmm))
+ exynos_drm_iommu_deactivate(drm_priv->vmm, ippdrv->dev);
+
+ return ret;
+}
+
+static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
+{
+ struct exynos_drm_ippdrv *ippdrv;
+ struct exynos_drm_private *drm_priv = drm_dev->dev_private;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ /* get ipp driver entry */
+ list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) {
+
+ /* ToDo: need move close ? */
+
+ /* remove,destroy property idr */
+ idr_remove_all(&ippdrv->prop_idr);
+ idr_destroy(&ippdrv->prop_idr);
+
+ if (drm_priv->vmm)
+ exynos_drm_iommu_deactivate(drm_priv->vmm, ippdrv->dev);
+
+ ippdrv->drm_dev = NULL;
+ exynos_drm_ippdrv_unregister(ippdrv);
+ }
+
+ /* ToDo: free notifier callback list if needed */
+}
+
+static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
+ struct drm_file *file)
+{
+ struct drm_exynos_file_private *file_priv = file->driver_priv;
+ struct exynos_drm_ipp_private *priv;
+ struct exynos_drm_ippdrv *ippdrv;
+ int count = 0;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ /* ToDo: multi device open */
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ DRM_ERROR("failed to allocate priv.\n");
+ return -ENOMEM;
+ }
+
+ priv->dev = dev;
+ file_priv->ipp_priv = priv;
+ INIT_LIST_HEAD(&priv->event_list);
+
+ /* get ipp driver entry */
+ list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) {
+ DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]\n", __func__,
+ count++, (int)ippdrv);
+
+ /* check idle state */
+ if (ippdrv->state != IPP_STATE_IDLE)
+ continue;
+
+ INIT_LIST_HEAD(&ippdrv->event_list);
+ INIT_LIST_HEAD(&ippdrv->cmd_list);
+ list_splice_init(&priv->event_list, &ippdrv->event_list);
+ }
+
+ return 0;
+}
+
+static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
+ struct drm_file *file)
+{
+ struct drm_exynos_file_private *file_priv = file->driver_priv;
+ struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
+ struct exynos_drm_ippdrv *ippdrv_cur = priv->ippdrv;
+ struct exynos_drm_ippdrv *ippdrv;
+ struct drm_exynos_ipp_send_event *e, *te;
+ int count;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ /* ToDo: for multi device close */
+
+ /* get ipp driver entry */
+ list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) {
+ DRM_DEBUG_KMS("%s:ippdrv_cur[0x%x]ippdrv[0x%x]\n",
+ __func__, (int)ippdrv_cur, (int)ippdrv);
+
+ DRM_DEBUG_KMS("%s:state[%d]dedicated[%d]\n", __func__,
+ ippdrv->state, ippdrv->dedicated);
+
+ /* current used ippdrv stop needed */
+ if (ippdrv_cur && ippdrv_cur == ippdrv) {
+ if (ippdrv->state == IPP_STATE_START) {
+ if (ippdrv->stop)
+ ippdrv->stop(ippdrv->dev, ippdrv->cmd);
+
+ if (!pm_runtime_suspended(ippdrv->dev))
+ pm_runtime_put_sync(ippdrv->dev);
+ }
+
+ ippdrv->state = IPP_STATE_IDLE;
+ ippdrv->dedicated = false;
+ }
+
+ /* check idle state */
+ if (ippdrv->state != IPP_STATE_IDLE)
+ continue;
+
+ /* free event */
+ count = 0;
+ list_for_each_entry_safe(e, te,
+ &ippdrv->event_list, base.link) {
+ DRM_DEBUG_KMS("%s:count[%d]e[0x%x]\n",
+ __func__, count++, (int)e);
+
+ /* delete list */
+ list_del(&e->base.link);
+ kfree(e);
+ }
+
+ /* free property list */
+ ipp_free_cmd_list(drm_dev, ippdrv);
+ /* ToDo: How can get current fd property ? */
+ }
+
+ kfree(file_priv->ipp_priv);
+
+ return;
+}
+
+static int __devinit ipp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ipp_context *ctx;
+ struct exynos_drm_subdrv *subdrv;
+ struct exynos_drm_ippdrv *tippdrv;
+ int ret = -EINVAL;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ /* init ioctl lock */
+ mutex_init(&ctx->lock);
+ /* init event, cmd work thread */
+ INIT_WORK(&ctx->sched_event, ipp_sched_event);
+ INIT_WORK(&ctx->sched_cmd, ipp_sched_cmd);
+ /* init ipp driver idr */
+ idr_init(&ctx->ipp_idr);
+
+ /* get ipp driver entry */
+ list_for_each_entry(tippdrv, &exynos_drm_ippdrv_list, list) {
+ /* create ipp id */
+ ret = ipp_create_id(&ctx->ipp_idr, tippdrv, &tippdrv->ipp_id);
+ if (ret) {
+ DRM_ERROR("failed to create id.\n");
+ goto err_clear;
+ }
+
+ DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, tippdrv->ipp_id);
+
+ if (tippdrv->ipp_id == 0)
+ DRM_ERROR("failed to get ipp_id[%d]\n",
+ tippdrv->ipp_id);
+ }
+
+ /* set sub driver informations */
+ subdrv = &ctx->subdrv;
+ subdrv->dev = dev;
+ subdrv->probe = ipp_subdrv_probe;
+ subdrv->remove = ipp_subdrv_remove;
+ subdrv->open = ipp_subdrv_open;
+ subdrv->close = ipp_subdrv_close;
+
+ /* set driver data */
+ platform_set_drvdata(pdev, ctx);
+
+ /* register sub driver */
+ ret = exynos_drm_subdrv_register(subdrv);
+ if (ret < 0) {
+ DRM_ERROR("failed to register drm ipp device.\n");
+ goto err_clear;
+ }
+
+ dev_info(&pdev->dev, "drm ipp registered successfully.\n");
+
+ return 0;
+
+err_clear:
+ kfree(ctx);
+
+ return ret;
+}
+
+static int __devexit ipp_remove(struct platform_device *pdev)
+{
+ struct ipp_context *ctx = platform_get_drvdata(pdev);
+
+ DRM_DEBUG_KMS("%s\n", __func__);
+
+ /* unregister sub driver */
+ exynos_drm_subdrv_unregister(&ctx->subdrv);
+
+ /* remove,destroy ipp idr */
+ idr_remove_all(&ctx->ipp_idr);
+ idr_destroy(&ctx->ipp_idr);
+
+ kfree(ctx);
+
+ return 0;
+}
+
+
+struct platform_driver ipp_driver = {
+ .probe = ipp_probe,
+ .remove = __devexit_p(ipp_remove),
+ .driver = {
+ .name = "exynos-drm-ipp",
+ .owner = THIS_MODULE,
+ },
+};
+
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
new file mode 100644
index 0000000..458f747
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Authors:
+ * Eunchul Kim <chulspro.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_IPP_H_
+#define _EXYNOS_DRM_IPP_H_
+
+#define IPP_GET_LCD_WIDTH _IOR('F', 302, int)
+#define IPP_GET_LCD_HEIGHT _IOR('F', 303, int)
+#define IPP_SET_WRITEBACK _IOW('F', 304, u32)
+
+/* definition of state */
+enum drm_exynos_ipp_state {
+ IPP_STATE_IDLE,
+ IPP_STATE_START,
+ IPP_STATE_STOP,
+};
+
+/*
+ * A structure of buffer information.
+ *
+ * @gem_objs: Y, Cb, Cr each gem object.
+ * @base: Y, Cb, Cr each planar address.
+ * @size: Y, Cb, Cr each planar size.
+ */
+struct drm_exynos_ipp_buf_info {
+ void *gem_objs[EXYNOS_DRM_PLANAR_MAX];
+ dma_addr_t base[EXYNOS_DRM_PLANAR_MAX];
+ uint64_t size[EXYNOS_DRM_PLANAR_MAX];
+};
+
+/*
+ * A structure of source,destination operations.
+ *
+ * @set_fmt: set format of image.
+ * @set_transf: set transform(rotations, flip).
+ * @set_size: set size of region.
+ * @set_addr: set address for dma.
+ */
+struct exynos_drm_ipp_ops {
+ int (*set_fmt)(struct device *dev, u32 fmt);
+ int (*set_transf)(struct device *dev,
+ enum drm_exynos_degree degree,
+ enum drm_exynos_flip flip);
+ int (*set_size)(struct device *dev, int swap,
+ struct drm_exynos_pos *pos, struct drm_exynos_sz *sz);
+ int (*set_addr)(struct device *dev,
+ struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
+ enum drm_exynos_ipp_buf_ctrl buf_ctrl);
+};
+
+/*
+ * A structure of ipp driver.
+ *
+ * @list: list head.
+ * @dev: platform device.
+ * @drm_dev: drm device.
+ * @state: state of ipp drivers.
+ * @ipp_id: id of ipp driver.
+ * @dedicated: dedicated ipp device.
+ * @iommu_used: iommu used status.
+ * @cmd: used command.
+ * @ops: source, destination operations.
+ * @property: current property.
+ * @prop_idr: property idr.
+ * @cmd_list: list head to command information.
+ * @event_list: list head to event information.
+ * @reset: reset ipp block.
+ * @check_property: check property about format, size, buffer.
+ * @start: ipp each device start.
+ * @stop: ipp each device stop.
+ */
+struct exynos_drm_ippdrv {
+ struct list_head list;
+ struct device *dev;
+ struct drm_device *drm_dev;
+ enum drm_exynos_ipp_state state;
+ u32 ipp_id;
+ bool dedicated;
+ bool iommu_used;
+ enum drm_exynos_ipp_cmd cmd;
+ struct exynos_drm_ipp_ops *ops[EXYNOS_DRM_OPS_MAX];
+ struct drm_exynos_ipp_property *property;
+ struct idr prop_idr;
+ struct list_head cmd_list;
+ struct list_head event_list;
+
+ int (*check_property)(struct device *dev,
+ struct drm_exynos_ipp_property *property);
+ int (*reset)(struct device *dev);
+ int (*start)(struct device *dev, enum drm_exynos_ipp_cmd cmd);
+ void (*stop)(struct device *dev, enum drm_exynos_ipp_cmd cmd);
+};
+
+#ifdef CONFIG_DRM_EXYNOS_IPP
+extern int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv);
+extern int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv);
+extern int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
+ struct drm_file *file);
+extern int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
+ struct drm_file *file);
+extern int exynos_drm_ipp_buf(struct drm_device *drm_dev, void *data,
+ struct drm_file *file);
+extern int exynos_drm_ipp_ctrl(struct drm_device *drm_dev, void *data,
+ struct drm_file *file);
+extern int exynos_drm_ippnb_register(struct notifier_block *nb);
+extern int exynos_drm_ippnb_unregister(struct notifier_block *nb);
+extern int exynos_drm_ippnb_send_event(unsigned long val, void *v);
+#else
+static inline int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
+{
+ return -ENODEV;
+}
+
+static inline int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
+{
+ return -ENODEV;
+}
+
+static inline int exynos_drm_ipp_get_property(struct drm_device *drm_dev,
+ void *data,
+ struct drm_file *file_priv)
+{
+ return -ENOTTY;
+}
+
+static inline int exynos_drm_ipp_set_property(struct drm_device *drm_dev,
+ void *data,
+ struct drm_file *file_priv)
+{
+ return -ENOTTY;
+}
+
+static inline int exynos_drm_ipp_buf(struct drm_device *drm_dev,
+ void *data,
+ struct drm_file *file)
+{
+ return -ENOTTY;
+}
+
+static inline int exynos_drm_ipp_ctrl(struct drm_device *drm_dev,
+ void *data,
+ struct drm_file *file)
+{
+ return -ENOTTY;
+}
+
+static inline int exynos_drm_ippnb_register(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+
+static inline int exynos_drm_ippnb_unregister(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+
+static inline int exynos_drm_ippnb_send_event(unsigned long val, void *v)
+{
+ return -ENOTTY;
+}
+#endif
+
+/* ToDo: Must be change to queue_work */
+void ipp_send_event_handler(struct exynos_drm_ippdrv *ippdrv,
+ int buf_idx);
+
+#endif /* _EXYNOS_DRM_IPP_H_ */
+
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index c4c6525..b89829e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -12,9 +12,12 @@
#include "drmP.h"
#include "exynos_drm.h"
-#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_gem.h"
+
+#define to_exynos_plane(x) container_of(x, struct exynos_plane, base)
struct exynos_plane {
struct drm_plane base;
@@ -30,6 +33,108 @@ static const uint32_t formats[] = {
DRM_FORMAT_NV12MT,
};
+int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
+ struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h)
+{
+ struct exynos_plane *exynos_plane = to_exynos_plane(plane);
+ struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
+ unsigned int actual_w;
+ unsigned int actual_h;
+ int nr;
+ int i;
+
+ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
+
+ nr = exynos_drm_format_num_buffers(fb->pixel_format);
+ for (i = 0; i < nr; i++) {
+ struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i);
+
+ if (!buffer) {
+ DRM_LOG_KMS("buffer is null\n");
+ return -EFAULT;
+ }
+
+ overlay->dma_addr[i] = buffer->dma_addr;
+ overlay->vaddr[i] = buffer->kvaddr;
+
+ DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n",
+ i, (unsigned long)overlay->vaddr[i],
+ (unsigned long)overlay->dma_addr[i]);
+ }
+
+ actual_w = min((unsigned)(crtc->mode.hdisplay - crtc_x), crtc_w);
+ actual_h = min((unsigned)(crtc->mode.vdisplay - crtc_y), crtc_h);
+
+ /* set drm framebuffer data. */
+ overlay->fb_x = src_x;
+ overlay->fb_y = src_y;
+ overlay->fb_width = fb->width;
+ overlay->fb_height = fb->height;
+ overlay->src_width = src_w;
+ overlay->src_height = src_h;
+ overlay->bpp = fb->bits_per_pixel;
+ overlay->pitch = fb->pitches[0];
+ overlay->pixel_format = fb->pixel_format;
+
+ /* set overlay range to be displayed. */
+ overlay->crtc_x = crtc_x;
+ overlay->crtc_y = crtc_y;
+ overlay->crtc_width = actual_w;
+ overlay->crtc_height = actual_h;
+
+ /* set drm mode data. */
+ overlay->mode_width = crtc->mode.hdisplay;
+ overlay->mode_height = crtc->mode.vdisplay;
+ overlay->refresh = crtc->mode.vrefresh;
+ overlay->scan_flag = crtc->mode.flags;
+
+ DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
+ overlay->crtc_x, overlay->crtc_y,
+ overlay->crtc_width, overlay->crtc_height);
+
+ exynos_drm_fn_encoder(crtc, overlay, exynos_drm_encoder_plane_mode_set);
+
+ return 0;
+}
+
+void exynos_plane_commit(struct drm_plane *plane)
+{
+ struct exynos_plane *exynos_plane = to_exynos_plane(plane);
+ struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
+
+ exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
+ exynos_drm_encoder_plane_commit);
+}
+
+void exynos_plane_dpms(struct drm_plane *plane, int mode)
+{
+ struct exynos_plane *exynos_plane = to_exynos_plane(plane);
+ struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
+
+ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
+
+ if (mode == DRM_MODE_DPMS_ON) {
+ if (exynos_plane->enabled)
+ return;
+
+ exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
+ exynos_drm_encoder_plane_enable);
+
+ exynos_plane->enabled = true;
+ } else {
+ if (!exynos_plane->enabled)
+ return;
+
+ exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
+ exynos_drm_encoder_plane_disable);
+
+ exynos_plane->enabled = false;
+ }
+}
+
static int
exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
@@ -37,64 +142,37 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{
- struct exynos_plane *exynos_plane =
- container_of(plane, struct exynos_plane, base);
- struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
- struct exynos_drm_crtc_pos pos;
int ret;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
- memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos));
- pos.crtc_x = crtc_x;
- pos.crtc_y = crtc_y;
- pos.crtc_w = crtc_w;
- pos.crtc_h = crtc_h;
-
- /* considering 16.16 fixed point of source values */
- pos.fb_x = src_x >> 16;
- pos.fb_y = src_y >> 16;
- pos.src_w = src_w >> 16;
- pos.src_h = src_h >> 16;
-
- ret = exynos_drm_overlay_update(overlay, fb, &crtc->mode, &pos);
+ ret = exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
+ crtc_w, crtc_h, src_x >> 16, src_y >> 16,
+ src_w >> 16, src_h >> 16);
if (ret < 0)
return ret;
- exynos_drm_fn_encoder(crtc, overlay,
- exynos_drm_encoder_crtc_mode_set);
- exynos_drm_fn_encoder(crtc, &overlay->zpos,
- exynos_drm_encoder_crtc_plane_commit);
+ plane->crtc = crtc;
+ plane->fb = crtc->fb;
- exynos_plane->enabled = true;
+ exynos_plane_commit(plane);
+ exynos_plane_dpms(plane, DRM_MODE_DPMS_ON);
return 0;
}
static int exynos_disable_plane(struct drm_plane *plane)
{
- struct exynos_plane *exynos_plane =
- container_of(plane, struct exynos_plane, base);
- struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
-
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
- if (!exynos_plane->enabled)
- return 0;
-
- exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
- exynos_drm_encoder_crtc_disable);
-
- exynos_plane->enabled = false;
- exynos_plane->overlay.zpos = DEFAULT_ZPOS;
+ exynos_plane_dpms(plane, DRM_MODE_DPMS_OFF);
return 0;
}
static void exynos_plane_destroy(struct drm_plane *plane)
{
- struct exynos_plane *exynos_plane =
- container_of(plane, struct exynos_plane, base);
+ struct exynos_plane *exynos_plane = to_exynos_plane(plane);
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -103,69 +181,79 @@ static void exynos_plane_destroy(struct drm_plane *plane)
kfree(exynos_plane);
}
+static int exynos_plane_set_property(struct drm_plane *plane,
+ struct drm_property *property,
+ uint64_t val)
+{
+ struct drm_device *dev = plane->dev;
+ struct exynos_plane *exynos_plane = to_exynos_plane(plane);
+ struct exynos_drm_private *dev_priv = dev->dev_private;
+
+ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
+
+ if (property == dev_priv->plane_zpos_property) {
+ exynos_plane->overlay.zpos = val;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static struct drm_plane_funcs exynos_plane_funcs = {
.update_plane = exynos_update_plane,
.disable_plane = exynos_disable_plane,
.destroy = exynos_plane_destroy,
+ .set_property = exynos_plane_set_property,
};
-int exynos_plane_init(struct drm_device *dev, unsigned int nr)
+static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
{
- struct exynos_plane *exynos_plane;
- uint32_t possible_crtcs;
+ struct drm_device *dev = plane->dev;
+ struct exynos_drm_private *dev_priv = dev->dev_private;
+ struct drm_property *prop;
- exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL);
- if (!exynos_plane)
- return -ENOMEM;
+ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
- /* all CRTCs are available */
- possible_crtcs = (1 << MAX_CRTC) - 1;
+ prop = dev_priv->plane_zpos_property;
+ if (!prop) {
+ prop = drm_property_create_range(dev, 0, "zpos", 0,
+ MAX_PLANE - 1);
+ if (!prop)
+ return;
- exynos_plane->overlay.zpos = DEFAULT_ZPOS;
+ dev_priv->plane_zpos_property = prop;
+ }
- return drm_plane_init(dev, &exynos_plane->base, possible_crtcs,
- &exynos_plane_funcs, formats, ARRAY_SIZE(formats),
- false);
+ drm_object_attach_property(&plane->base, prop, 0);
}
-int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+struct drm_plane *exynos_plane_init(struct drm_device *dev,
+ unsigned int possible_crtcs, bool priv)
{
- struct drm_exynos_plane_set_zpos *zpos_req = data;
- struct drm_mode_object *obj;
- struct drm_plane *plane;
struct exynos_plane *exynos_plane;
- int ret = 0;
+ int err;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return -EINVAL;
-
- if (zpos_req->zpos < 0 || zpos_req->zpos >= MAX_PLANE) {
- if (zpos_req->zpos != DEFAULT_ZPOS) {
- DRM_ERROR("zpos not within limits\n");
- return -EINVAL;
- }
+ exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL);
+ if (!exynos_plane) {
+ DRM_ERROR("failed to allocate plane\n");
+ return NULL;
}
- mutex_lock(&dev->mode_config.mutex);
-
- obj = drm_mode_object_find(dev, zpos_req->plane_id,
- DRM_MODE_OBJECT_PLANE);
- if (!obj) {
- DRM_DEBUG_KMS("Unknown plane ID %d\n",
- zpos_req->plane_id);
- ret = -EINVAL;
- goto out;
+ err = drm_plane_init(dev, &exynos_plane->base, possible_crtcs,
+ &exynos_plane_funcs, formats, ARRAY_SIZE(formats),
+ priv);
+ if (err) {
+ DRM_ERROR("failed to initialize plane\n");
+ kfree(exynos_plane);
+ return NULL;
}
- plane = obj_to_plane(obj);
- exynos_plane = container_of(plane, struct exynos_plane, base);
-
- exynos_plane->overlay.zpos = zpos_req->zpos;
+ if (priv)
+ exynos_plane->overlay.zpos = DEFAULT_ZPOS;
+ else
+ exynos_plane_attach_zpos_property(&exynos_plane->base);
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
+ return &exynos_plane->base;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 16b71f8..8831245 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -9,6 +9,12 @@
*
*/
-int exynos_plane_init(struct drm_device *dev, unsigned int nr);
-int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
+ struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h);
+void exynos_plane_commit(struct drm_plane *plane);
+void exynos_plane_dpms(struct drm_plane *plane, int mode);
+struct drm_plane *exynos_plane_init(struct drm_device *dev,
+ unsigned int possible_crtcs, bool priv);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index 5bf1d6e..9e40790 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -15,13 +15,12 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
-#include <linux/pm_qos_params.h>
#include "drmP.h"
#include "exynos_drm.h"
#include "exynos_drm_drv.h"
-#include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h"
+#include "exynos_drm_ipp.h"
/* Configuration */
#define ROT_CONFIG 0x00
@@ -49,39 +48,31 @@
#define ROT_STATUS_IRQ_VAL_COMPLETE 1
#define ROT_STATUS_IRQ_VAL_ILLEGAL 2
-/* Sourc Buffer Address */
+/* Buffer Address */
#define ROT_SRC_BUF_ADDR(n) (0x30 + ((n) << 2))
+#define ROT_DST_BUF_ADDR(n) (0x50 + ((n) << 2))
-/* Source Buffer Size */
+/* Buffer Size */
#define ROT_SRC_BUF_SIZE 0x3c
-#define ROT_SRC_BUF_SIZE_H(x) ((x) << 16)
-#define ROT_SRC_BUF_SIZE_W(x) ((x) << 0)
+#define ROT_DST_BUF_SIZE 0x5c
+#define ROT_SET_BUF_SIZE_H(x) ((x) << 16)
+#define ROT_SET_BUF_SIZE_W(x) ((x) << 0)
+#define ROT_GET_BUF_SIZE_H(x) ((x) >> 16)
+#define ROT_GET_BUF_SIZE_W(x) ((x) & 0xffff)
-/* Source Crop Position */
+/* Crop Position */
#define ROT_SRC_CROP_POS 0x40
-#define ROT_SRC_CROP_POS_Y(x) ((x) << 16)
-#define ROT_SRC_CROP_POS_X(x) ((x) << 0)
+#define ROT_DST_CROP_POS 0x60
+#define ROT_CROP_POS_Y(x) ((x) << 16)
+#define ROT_CROP_POS_X(x) ((x) << 0)
/* Source Crop Size */
#define ROT_SRC_CROP_SIZE 0x44
#define ROT_SRC_CROP_SIZE_H(x) ((x) << 16)
#define ROT_SRC_CROP_SIZE_W(x) ((x) << 0)
-/* Destination Buffer Address */
-#define ROT_DST_BUF_ADDR(n) (0x50 + ((n) << 2))
-
-/* Destination Buffer Size */
-#define ROT_DST_BUF_SIZE 0x5c
-#define ROT_DST_BUF_SIZE_H(x) ((x) << 16)
-#define ROT_DST_BUF_SIZE_W(x) ((x) << 0)
-
-/* Destination Crop Position */
-#define ROT_DST_CROP_POS 0x60
-#define ROT_DST_CROP_POS_Y(x) ((x) << 16)
-#define ROT_DST_CROP_POS_X(x) ((x) << 0)
-
/* Round to nearest aligned value */
-#define ROT_ALIGN(x, align, mask) ((*(x) + (1 << ((align) - 1))) & (mask))
+#define ROT_ALIGN(x, align, mask) (((x) + (1 << ((align) - 1))) & (mask))
/* Minimum limit value */
#define ROT_MIN(min, mask) (((min) + ~(mask)) & (mask))
/* Maximum limit value */
@@ -111,28 +102,11 @@ struct rot_context {
struct resource *regs_res;
void __iomem *regs;
int irq;
- int exec_ret;
- struct exynos_drm_subdrv subdrv;
- struct completion complete;
- struct mutex exec_mutex;
- spinlock_t irq_lock;
- struct pm_qos_request_list pm_qos;
+ struct exynos_drm_ippdrv ippdrv;
+ int cur_buf_id[EXYNOS_DRM_OPS_MAX];
bool suspended;
};
-struct rot_buffer {
- dma_addr_t src_addr[DRM_EXYNOS_ROT_MAX_BUF];
- dma_addr_t dst_addr[DRM_EXYNOS_ROT_MAX_BUF];
- void *src_gem_obj[DRM_EXYNOS_ROT_MAX_BUF];
- void *dst_gem_obj[DRM_EXYNOS_ROT_MAX_BUF];
- u32 src_cnt;
- u32 dst_cnt;
- u32 src_w;
- u32 src_h;
- u32 dst_w;
- u32 dst_h;
-};
-
static void rotator_reg_set_irq(struct rot_context *rot, bool enable)
{
u32 value = readl(rot->regs + ROT_CONFIG);
@@ -145,6 +119,14 @@ static void rotator_reg_set_irq(struct rot_context *rot, bool enable)
writel(value, rot->regs + ROT_CONFIG);
}
+static u32 rotator_reg_get_format(struct rot_context *rot)
+{
+ u32 value = readl(rot->regs + ROT_CONTROL);
+ value &= ROT_CONTROL_FMT_MASK;
+
+ return value;
+}
+
static void rotator_reg_set_format(struct rot_context *rot, u32 img_fmt)
{
u32 value = readl(rot->regs + ROT_CONTROL);
@@ -155,7 +137,7 @@ static void rotator_reg_set_format(struct rot_context *rot, u32 img_fmt)
case DRM_FORMAT_NV12M:
value |= ROT_CONTROL_FMT_YCBCR420_2P;
break;
- case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_XRGB8888:
value |= ROT_CONTROL_FMT_RGB888;
break;
default:
@@ -167,16 +149,16 @@ static void rotator_reg_set_format(struct rot_context *rot, u32 img_fmt)
}
static void rotator_reg_set_flip(struct rot_context *rot,
- enum drm_exynos_rot_flip flip)
+ enum drm_exynos_flip flip)
{
u32 value = readl(rot->regs + ROT_CONTROL);
value &= ~ROT_CONTROL_FLIP_MASK;
switch (flip) {
- case ROT_FLIP_VERTICAL:
+ case EXYNOS_DRM_FLIP_VERTICAL:
value |= ROT_CONTROL_FLIP_VERTICAL;
break;
- case ROT_FLIP_HORIZONTAL:
+ case EXYNOS_DRM_FLIP_HORIZONTAL:
value |= ROT_CONTROL_FLIP_HORIZONTAL;
break;
default:
@@ -188,19 +170,19 @@ static void rotator_reg_set_flip(struct rot_context *rot,
}
static void rotator_reg_set_rotation(struct rot_context *rot,
- enum drm_exynos_rot_degree degree)
+ enum drm_exynos_degree degree)
{
u32 value = readl(rot->regs + ROT_CONTROL);
value &= ~ROT_CONTROL_ROT_MASK;
switch (degree) {
- case ROT_DEGREE_90:
+ case EXYNOS_DRM_DEGREE_90:
value |= ROT_CONTROL_ROT_90;
break;
- case ROT_DEGREE_180:
+ case EXYNOS_DRM_DEGREE_180:
value |= ROT_CONTROL_ROT_180;
break;
- case ROT_DEGREE_270:
+ case EXYNOS_DRM_DEGREE_270:
value |= ROT_CONTROL_ROT_270;
break;
default:
@@ -247,16 +229,25 @@ static void rotator_reg_set_src_buf_addr(struct rot_context *rot,
writel(addr, rot->regs + ROT_SRC_BUF_ADDR(i));
}
+static void rotator_reg_get_src_buf_size(struct rot_context *rot, u32 *w,
+ u32 *h)
+{
+ u32 value = readl(rot->regs + ROT_SRC_BUF_SIZE);
+
+ *w = ROT_GET_BUF_SIZE_W(value);
+ *h = ROT_GET_BUF_SIZE_H(value);
+}
+
static void rotator_reg_set_src_buf_size(struct rot_context *rot, u32 w, u32 h)
{
- u32 value = ROT_SRC_BUF_SIZE_H(h) | ROT_SRC_BUF_SIZE_W(w);
+ u32 value = ROT_SET_BUF_SIZE_H(h) | ROT_SET_BUF_SIZE_W(w);
writel(value, rot->regs + ROT_SRC_BUF_SIZE);
}
static void rotator_reg_set_src_crop_pos(struct rot_context *rot, u32 x, u32 y)
{
- u32 value = ROT_SRC_CROP_POS_Y(y) | ROT_SRC_CROP_POS_X(x);
+ u32 value = ROT_CROP_POS_Y(y) | ROT_CROP_POS_X(x);
writel(value, rot->regs + ROT_SRC_CROP_POS);
}
@@ -274,16 +265,25 @@ static void rotator_reg_set_dst_buf_addr(struct rot_context *rot,
writel(addr, rot->regs + ROT_DST_BUF_ADDR(i));
}
+static void rotator_reg_get_dst_buf_size(struct rot_context *rot, u32 *w,
+ u32 *h)
+{
+ u32 value = readl(rot->regs + ROT_DST_BUF_SIZE);
+
+ *w = ROT_GET_BUF_SIZE_W(value);
+ *h = ROT_GET_BUF_SIZE_H(value);
+}
+
static void rotator_reg_set_dst_buf_size(struct rot_context *rot, u32 w, u32 h)
{
- u32 value = ROT_DST_BUF_SIZE_H(h) | ROT_DST_BUF_SIZE_W(w);
+ u32 value = ROT_SET_BUF_SIZE_H(h) | ROT_SET_BUF_SIZE_W(w);
writel(value, rot->regs + ROT_DST_BUF_SIZE);
}
static void rotator_reg_set_dst_crop_pos(struct rot_context *rot, u32 x, u32 y)
{
- u32 value = ROT_DST_CROP_POS_Y(y) | ROT_DST_CROP_POS_X(x);
+ u32 value = ROT_CROP_POS_Y(y) | ROT_CROP_POS_X(x);
writel(value, rot->regs + ROT_DST_CROP_POS);
}
@@ -294,71 +294,40 @@ static void rotator_reg_get_dump(struct rot_context *rot)
for (i = 0; i <= ROT_DST_CROP_POS; i += 0x4) {
value = readl(rot->regs + i);
- DRM_INFO("+0x%x: 0x%x", i, value);
+ DRM_INFO("[%s] [0x%x] : 0x%x\n", __func__, i, value);
}
}
-static bool rotator_check_format_n_handle_valid(u32 img_fmt,
- u32 src_buf_handle_cnt,
- u32 dst_buf_handle_cnt)
+static irqreturn_t rotator_irq_handler(int irq, void *arg)
{
- bool ret = false;
+ struct rot_context *rot = arg;
+ struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
+ enum rot_irq_status irq_status;
- if ((src_buf_handle_cnt != dst_buf_handle_cnt)
- || (src_buf_handle_cnt == 0))
- return ret;
+ /* Get execution result */
+ irq_status = rotator_reg_get_irq_status(rot);
+ rotator_reg_set_irq_status_clear(rot, irq_status);
- switch (img_fmt) {
- case DRM_FORMAT_NV12M:
- if (src_buf_handle_cnt == 2)
- ret = true;
- break;
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_RGB888:
- if (src_buf_handle_cnt == 1)
- ret = true;
- break;
- default:
- DRM_ERROR("invalid image format\n");
- break;
+ if (irq_status == ROT_IRQ_STATUS_COMPLETE)
+ ipp_send_event_handler(ippdrv,
+ rot->cur_buf_id[EXYNOS_DRM_OPS_DST]);
+ else {
+ DRM_ERROR("the SFR is set illegally\n");
+ rotator_reg_get_dump(rot);
}
- return ret;
-}
-
-static void rotator_align_size(struct rot_limit *limit, u32 mask, u32 *w,
- u32 *h)
-{
- u32 value;
-
- value = ROT_ALIGN(w, limit->align, mask);
- if (value < limit->min_w)
- *w = ROT_MIN(limit->min_w, mask);
- else if (value > limit->max_w)
- *w = ROT_MAX(limit->max_w, mask);
- else
- *w = value;
-
- value = ROT_ALIGN(h, limit->align, mask);
- if (value < limit->min_h)
- *h = ROT_MIN(limit->min_h, mask);
- else if (value > limit->max_h)
- *h = ROT_MAX(limit->max_h, mask);
- else
- *h = value;
+ return IRQ_HANDLED;
}
-static void rotator_align_buffer(struct rot_context *rot,
- struct rot_buffer *buf,
- struct drm_exynos_rot_buffer *req_buf,
- struct drm_exynos_rot_control *control)
+static void rotator_align_size(struct rot_context *rot, u32 fmt, u32 *hsize,
+ u32 *vsize)
{
struct rot_limit_table *limit_tbl = rot->limit_tbl;
struct rot_limit *limit;
- u32 mask;
+ u32 mask, value;
/* Get size limit */
- if (control->img_fmt == DRM_FORMAT_RGB888)
+ if (fmt == ROT_CONTROL_FMT_RGB888)
limit = &limit_tbl->rgb888;
else
limit = &limit_tbl->ycbcr420_2p;
@@ -366,310 +335,333 @@ static void rotator_align_buffer(struct rot_context *rot,
/* Get mask for rounding to nearest aligned value */
mask = ~((1 << limit->align) - 1);
- /* For source buffer */
- buf->src_w = req_buf->src_w;
- buf->src_h = req_buf->src_h;
- rotator_align_size(limit, mask, &buf->src_w, &buf->src_h);
+ /* Set aligned width */
+ value = ROT_ALIGN(*hsize, limit->align, mask);
+ if (value < limit->min_w)
+ *hsize = ROT_MIN(limit->min_w, mask);
+ else if (value > limit->max_w)
+ *hsize = ROT_MAX(limit->max_w, mask);
+ else
+ *hsize = value;
- /* For destination buffer */
- buf->dst_w = req_buf->dst_w;
- buf->dst_h = req_buf->dst_h;
- rotator_align_size(limit, mask, &buf->dst_w, &buf->dst_h);
+ /* Set aligned height */
+ value = ROT_ALIGN(*vsize, limit->align, mask);
+ if (value < limit->min_h)
+ *vsize = ROT_MIN(limit->min_h, mask);
+ else if (value > limit->max_h)
+ *vsize = ROT_MAX(limit->max_h, mask);
+ else
+ *vsize = value;
}
-static bool rotator_check_crop_boundary(struct rot_buffer *buf,
- struct drm_exynos_rot_control *control,
- struct drm_exynos_rot_crop *crop)
+static int rotator_src_set_fmt(struct device *dev, u32 fmt)
{
- bool ret = true;
+ struct rot_context *rot = dev_get_drvdata(dev);
- /* Check source crop position */
- if ((crop->src_x + crop->src_w > buf->src_w)
- || (crop->src_y + crop->src_h > buf->src_h))
- return false;
+ /* Set format configuration */
+ rotator_reg_set_format(rot, fmt);
- /* Check destination crop position */
- switch (control->degree) {
- case ROT_DEGREE_90:
- case ROT_DEGREE_270:
- if ((crop->dst_x + crop->src_h > buf->dst_w)
- || (crop->dst_y + crop->src_w > buf->dst_h))
- ret = false;
- break;
- default:
- if ((crop->dst_x + crop->src_w > buf->dst_w)
- || (crop->dst_y + crop->src_h > buf->dst_h))
- ret = false;
- break;
- }
-
- return ret;
+ return 0;
}
-static int rotator_iommu_map(struct rot_buffer *buf,
- struct drm_exynos_rot_buffer *req_buf,
- struct iommu_gem_map_params *params,
- struct list_head *iommu_list)
-{
- /* For source buffer */
- buf->src_cnt = 0;
- while (buf->src_cnt < req_buf->src_cnt) {
- buf->src_addr[buf->src_cnt] = exynos_drm_iommu_map_gem(params,
- iommu_list,
- req_buf->src_handle[buf->src_cnt],
- IOMMU_ROTATOR);
- if (!buf->src_addr[buf->src_cnt]) {
- DRM_ERROR("failed to map src handle[%u]\n",
- buf->src_cnt);
- return -EINVAL;
- }
- buf->src_gem_obj[(buf->src_cnt)++] = params->gem_obj;
- }
+static int rotator_src_set_size(struct device *dev, int swap,
+ struct drm_exynos_pos *pos,
+ struct drm_exynos_sz *sz)
+{
+ struct rot_context *rot = dev_get_drvdata(dev);
+ u32 fmt, hsize, vsize;
- /* For destination buffer */
- buf->dst_cnt = 0;
- while (buf->dst_cnt < req_buf->dst_cnt) {
- buf->dst_addr[buf->dst_cnt] = exynos_drm_iommu_map_gem(params,
- iommu_list,
- req_buf->dst_handle[buf->dst_cnt],
- IOMMU_ROTATOR);
- if (!buf->dst_addr[buf->dst_cnt]) {
- DRM_ERROR("failed to map dst handle[%u]\n",
- buf->dst_cnt);
- return -EINVAL;
- }
- buf->dst_gem_obj[(buf->dst_cnt)++] = params->gem_obj;
- }
+ /* Get format */
+ fmt = rotator_reg_get_format(rot);
- return 0;
-}
+ /* Align buffer size */
+ hsize = sz->hsize;
+ vsize = sz->vsize;
+ rotator_align_size(rot, fmt, &hsize, &vsize);
-static void rotator_iommu_unmap(struct rot_buffer *buf,
- struct iommu_gem_map_params *params)
-{
- /* For destination buffer */
- while (buf->dst_cnt > 0) {
- params->gem_obj = buf->dst_gem_obj[--(buf->dst_cnt)];
- exynos_drm_iommu_unmap_gem(params,
- buf->dst_addr[buf->dst_cnt],
- IOMMU_ROTATOR);
- }
+ /* Set buffer size configuration */
+ rotator_reg_set_src_buf_size(rot, hsize, vsize);
- /* For source buffer */
- while (buf->src_cnt > 0) {
- params->gem_obj = buf->src_gem_obj[--(buf->src_cnt)];
- exynos_drm_iommu_unmap_gem(params,
- buf->src_addr[buf->src_cnt],
- IOMMU_ROTATOR);
- }
+ /* Set crop image position configuration */
+ rotator_reg_set_src_crop_pos(rot, pos->x, pos->y);
+ rotator_reg_set_src_crop_size(rot, pos->w, pos->h);
+
+ return 0;
}
-static void rotator_execute(struct rot_context *rot,
- struct rot_buffer *buf,
- struct drm_exynos_rot_control *control,
- struct drm_exynos_rot_crop *crop)
+static int rotator_src_set_addr(struct device *dev,
+ struct drm_exynos_ipp_buf_info *buf_info,
+ u32 buf_id, enum drm_exynos_ipp_buf_ctrl ctrl)
{
+ struct rot_context *rot = dev_get_drvdata(dev);
+ dma_addr_t addr[EXYNOS_DRM_PLANAR_MAX];
+ u32 fmt, hsize, vsize;
int i;
- pm_runtime_get_sync(rot->subdrv.dev);
-
- /* Set interrupt enable */
- rotator_reg_set_irq(rot, true);
+ /* Set current buf_id */
+ rot->cur_buf_id[EXYNOS_DRM_OPS_SRC] = buf_id;
- /* Set control registers */
- rotator_reg_set_format(rot, control->img_fmt);
- rotator_reg_set_flip(rot, control->flip);
- rotator_reg_set_rotation(rot, control->degree);
+ switch (ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ /* Set address configuration */
+ for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++)
+ addr[i] = buf_info->base[i];
- /* Set source buffer address */
- for (i = 0; i < DRM_EXYNOS_ROT_MAX_BUF; i++)
- rotator_reg_set_src_buf_addr(rot, buf->src_addr[i], i);
+ /* Get format */
+ fmt = rotator_reg_get_format(rot);
- /* Set source buffer size */
- rotator_reg_set_src_buf_size(rot, buf->src_w, buf->src_h);
+ /* Re-set cb planar for NV12 format */
+ if ((fmt == ROT_CONTROL_FMT_YCBCR420_2P) &&
+ (addr[EXYNOS_DRM_PLANAR_CB] == 0x00)) {
+ /* Get buf size */
+ rotator_reg_get_src_buf_size(rot, &hsize, &vsize);
- /* Set destination buffer address */
- for (i = 0; i < DRM_EXYNOS_ROT_MAX_BUF; i++)
- rotator_reg_set_dst_buf_addr(rot, buf->dst_addr[i], i);
+ /* Set cb planar */
+ addr[EXYNOS_DRM_PLANAR_CB] =
+ addr[EXYNOS_DRM_PLANAR_Y] + hsize * vsize;
+ }
- /* Set destination buffer size */
- rotator_reg_set_dst_buf_size(rot, buf->dst_w, buf->dst_h);
+ for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++)
+ rotator_reg_set_src_buf_addr(rot, addr[i], i);
+ break;
+ case IPP_BUF_CTRL_DEQUEUE:
+ for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++)
+ rotator_reg_set_src_buf_addr(rot, buf_info->base[i], i);
+ break;
+ default:
+ /* Nothing to do */
+ break;
+ }
- /* Set source crop image position */
- rotator_reg_set_src_crop_pos(rot, crop->src_x, crop->src_y);
+ return 0;
+}
- /* Set source crop image size */
- rotator_reg_set_src_crop_size(rot, crop->src_w, crop->src_h);
+static int rotator_dst_set_transf(struct device *dev,
+ enum drm_exynos_degree degree,
+ enum drm_exynos_flip flip)
+{
+ struct rot_context *rot = dev_get_drvdata(dev);
- /* Set destination crop image position */
- rotator_reg_set_dst_crop_pos(rot, crop->dst_x, crop->dst_y);
+ /* Set transform configuration */
+ rotator_reg_set_flip(rot, flip);
+ rotator_reg_set_rotation(rot, degree);
- /* Start rotator operation */
- rotator_reg_set_start(rot);
+ /* Check degree for setting buffer size swap */
+ if ((degree == EXYNOS_DRM_DEGREE_90) ||
+ (degree == EXYNOS_DRM_DEGREE_270))
+ return 1;
+ else
+ return 0;
}
-int exynos_drm_rotator_exec_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file)
+static int rotator_dst_set_size(struct device *dev, int swap,
+ struct drm_exynos_pos *pos,
+ struct drm_exynos_sz *sz)
{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_rot_private *priv = file_priv->rot_priv;
- struct device *dev = priv->dev;
- struct rot_context *rot;
- struct drm_exynos_rot_exec_data *req = data;
- struct drm_exynos_rot_buffer *req_buf = &req->buf;
- struct drm_exynos_rot_control *control = &req->control;
- struct drm_exynos_rot_crop *crop = &req->crop;
- struct rot_buffer buf;
- struct iommu_gem_map_params params;
-
- if (!dev) {
- DRM_ERROR("failed to get dev\n");
- return -ENODEV;
- }
+ struct rot_context *rot = dev_get_drvdata(dev);
+ u32 fmt, hsize, vsize;
- rot = dev_get_drvdata(dev);
- if (!rot) {
- DRM_ERROR("failed to get drvdata\n");
- return -EFAULT;
- }
+ /* Get format */
+ fmt = rotator_reg_get_format(rot);
- if (rot->suspended) {
- DRM_ERROR("suspended state\n");
- return -EPERM;
- }
-
- if (!rotator_check_format_n_handle_valid(control->img_fmt,
- req_buf->src_cnt,
- req_buf->dst_cnt)) {
- DRM_ERROR("format or handles are invalid\n");
- return -EINVAL;
- }
+ /* Align buffer size */
+ hsize = sz->hsize;
+ vsize = sz->vsize;
+ rotator_align_size(rot, fmt, &hsize, &vsize);
- init_completion(&rot->complete);
+ /* Set buffer size configuration */
+ rotator_reg_set_dst_buf_size(rot, hsize, vsize);
- /* Align buffer */
- rotator_align_buffer(rot, &buf, req_buf, control);
+ /* Set crop image position configuration */
+ rotator_reg_set_dst_crop_pos(rot, pos->x, pos->y);
- /* Check crop boundary */
- if (!rotator_check_crop_boundary(&buf, control, crop)) {
- DRM_ERROR("boundary errror\n");
- return -EINVAL;
- }
+ return 0;
+}
- params.dev = dev;
- params.drm_dev = drm_dev;
- params.file = file;
+static int rotator_dst_set_addr(struct device *dev,
+ struct drm_exynos_ipp_buf_info *buf_info,
+ u32 buf_id, enum drm_exynos_ipp_buf_ctrl ctrl)
+{
+ struct rot_context *rot = dev_get_drvdata(dev);
+ dma_addr_t addr[EXYNOS_DRM_PLANAR_MAX];
+ u32 fmt, hsize, vsize;
+ int i;
- /* Map IOMMU */
- rot->exec_ret = rotator_iommu_map(&buf, req_buf, &params,
- &priv->iommu_list);
- if (rot->exec_ret < 0)
- goto err_iommu_map;
+ /* Set current buf_id */
+ rot->cur_buf_id[EXYNOS_DRM_OPS_DST] = buf_id;
- /* Assign another src/dst_addr for NV12 image format */
- if (control->img_fmt == DRM_FORMAT_NV12) {
- u32 size = crop->src_w * crop->src_h;
+ switch (ctrl) {
+ case IPP_BUF_CTRL_QUEUE:
+ /* Set address configuration */
+ for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++)
+ addr[i] = buf_info->base[i];
- buf.src_addr[buf.src_cnt + 1] =
- buf.src_addr[buf.src_cnt] + size;
- buf.dst_addr[buf.dst_cnt + 1] =
- buf.dst_addr[buf.dst_cnt] + size;
- }
+ /* Get format */
+ fmt = rotator_reg_get_format(rot);
- /* Execute */
- mutex_lock(&rot->exec_mutex);
- rotator_execute(rot, &buf, control, crop);
- if (!wait_for_completion_timeout(&rot->complete, 2 * HZ)) {
- DRM_ERROR("timeout error\n");
- rot->exec_ret = -ETIMEDOUT;
- mutex_unlock(&rot->exec_mutex);
- goto err_iommu_map;
- }
- mutex_unlock(&rot->exec_mutex);
+ /* Re-set cb planar for NV12 format */
+ if ((fmt == ROT_CONTROL_FMT_YCBCR420_2P) &&
+ (addr[EXYNOS_DRM_PLANAR_CB] == 0x00)) {
+ /* Get buf size */
+ rotator_reg_get_dst_buf_size(rot, &hsize, &vsize);
- /* Unmap IOMMU */
- rotator_iommu_unmap(&buf, &params);
+ /* Set cb planar */
+ addr[EXYNOS_DRM_PLANAR_CB] =
+ addr[EXYNOS_DRM_PLANAR_Y] + hsize * vsize;
+ }
- return rot->exec_ret;
+ for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++)
+ rotator_reg_set_dst_buf_addr(rot, addr[i], i);
+ break;
+ case IPP_BUF_CTRL_DEQUEUE:
+ for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++)
+ rotator_reg_set_dst_buf_addr(rot, buf_info->base[i], i);
+ break;
+ default:
+ /* Nothing to do */
+ break;
+ }
-err_iommu_map:
- rotator_iommu_unmap(&buf, &params);
- return rot->exec_ret;
+ return 0;
}
-EXPORT_SYMBOL_GPL(exynos_drm_rotator_exec_ioctl);
-static irqreturn_t rotator_irq_thread(int irq, void *arg)
-{
- struct rot_context *rot = (struct rot_context *)arg;
- enum rot_irq_status irq_status;
- unsigned long flags;
+static struct exynos_drm_ipp_ops rot_src_ops = {
+ .set_fmt = rotator_src_set_fmt,
+ .set_size = rotator_src_set_size,
+ .set_addr = rotator_src_set_addr,
+};
- pm_qos_update_request(&rot->pm_qos, 0);
+static struct exynos_drm_ipp_ops rot_dst_ops = {
+ .set_transf = rotator_dst_set_transf,
+ .set_size = rotator_dst_set_size,
+ .set_addr = rotator_dst_set_addr,
+};
- /* Get execution result */
- spin_lock_irqsave(&rot->irq_lock, flags);
- irq_status = rotator_reg_get_irq_status(rot);
- rotator_reg_set_irq_status_clear(rot, irq_status);
- spin_unlock_irqrestore(&rot->irq_lock, flags);
+static int rotator_ippdrv_check_property(struct device *dev,
+ struct drm_exynos_ipp_property *property)
+{
+ struct drm_exynos_ipp_config *src_config =
+ &property->config[EXYNOS_DRM_OPS_SRC];
+ struct drm_exynos_ipp_config *dst_config =
+ &property->config[EXYNOS_DRM_OPS_DST];
+ struct drm_exynos_pos *src_pos = &src_config->pos;
+ struct drm_exynos_pos *dst_pos = &dst_config->pos;
+ struct drm_exynos_sz *src_sz = &src_config->sz;
+ struct drm_exynos_sz *dst_sz = &dst_config->sz;
+ bool swap = false;
+
+ /* Check format configuration */
+ if (src_config->fmt != dst_config->fmt) {
+ DRM_DEBUG_KMS("[%s]not support csc feature\n", __func__);
+ return -EINVAL;
+ }
- rot->exec_ret = 0;
- if (irq_status != ROT_IRQ_STATUS_COMPLETE) {
- DRM_ERROR("the SFR is set illegally\n");
- rot->exec_ret = -EINVAL;
- rotator_reg_get_dump(rot);
+ switch (src_config->fmt) {
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV12M:
+ /* No problem */
+ break;
+ default:
+ DRM_DEBUG_KMS("[%s]not support format\n", __func__);
+ return -EINVAL;
}
- pm_runtime_put(rot->subdrv.dev);
+ /* Check transform configuration */
+ if (src_config->degree != EXYNOS_DRM_DEGREE_0) {
+ DRM_DEBUG_KMS("[%s]not support source-side rotation\n",
+ __func__);
+ return -EINVAL;
+ }
- complete(&rot->complete);
+ switch (dst_config->degree) {
+ case EXYNOS_DRM_DEGREE_90:
+ case EXYNOS_DRM_DEGREE_270:
+ swap = true;
+ case EXYNOS_DRM_DEGREE_0:
+ case EXYNOS_DRM_DEGREE_180:
+ /* No problem */
+ break;
+ default:
+ DRM_DEBUG_KMS("[%s]invalid degree\n", __func__);
+ return -EINVAL;
+ }
- return IRQ_HANDLED;
-}
+ if (src_config->flip != EXYNOS_DRM_FLIP_NONE) {
+ DRM_DEBUG_KMS("[%s]not support source-side flip\n", __func__);
+ return -EINVAL;
+ }
-static int rotator_subdrv_open(struct drm_device *drm_dev, struct device *dev,
- struct drm_file *file)
-{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_rot_private *priv;
+ switch (dst_config->flip) {
+ case EXYNOS_DRM_FLIP_NONE:
+ case EXYNOS_DRM_FLIP_VERTICAL:
+ case EXYNOS_DRM_FLIP_HORIZONTAL:
+ /* No problem */
+ break;
+ default:
+ DRM_DEBUG_KMS("[%s]invalid flip\n", __func__);
+ return -EINVAL;
+ }
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(dev, "failed to allocate priv\n");
- return -ENOMEM;
+ /* Check size configuration */
+ if ((src_pos->x + src_pos->w > src_sz->hsize) ||
+ (src_pos->y + src_pos->h > src_sz->vsize)) {
+ DRM_DEBUG_KMS("[%s]out of source buffer bound\n", __func__);
+ return -EINVAL;
}
- priv->dev = dev;
- INIT_LIST_HEAD(&priv->iommu_list);
+ if (swap) {
+ if ((dst_pos->x + dst_pos->h > dst_sz->vsize) ||
+ (dst_pos->y + dst_pos->w > dst_sz->hsize)) {
+ DRM_DEBUG_KMS("[%s]out of destination buffer bound\n",
+ __func__);
+ return -EINVAL;
+ }
- file_priv->rot_priv = priv;
+ if ((src_pos->w != dst_pos->h) || (src_pos->h != dst_pos->w)) {
+ DRM_DEBUG_KMS("[%s]not support scale feature\n",
+ __func__);
+ return -EINVAL;
+ }
+ } else {
+ if ((dst_pos->x + dst_pos->w > dst_sz->hsize) ||
+ (dst_pos->y + dst_pos->h > dst_sz->vsize)) {
+ DRM_DEBUG_KMS("[%s]out of destination buffer bound\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if ((src_pos->w != dst_pos->w) || (src_pos->h != dst_pos->h)) {
+ DRM_DEBUG_KMS("[%s]not support scale feature\n",
+ __func__);
+ return -EINVAL;
+ }
+ }
return 0;
}
-static void rotator_subdrv_close(struct drm_device *drm_dev, struct device *dev,
- struct drm_file *file)
+static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_rot_private *priv = file_priv->rot_priv;
- struct iommu_gem_map_params params;
- struct iommu_info_node *node, *n;
+ struct rot_context *rot = dev_get_drvdata(dev);
- params.dev = dev;
- params.drm_dev = drm_dev;
- params.file = file;
+ if (rot->suspended) {
+ DRM_ERROR("suspended state\n");
+ return -EPERM;
+ }
- list_for_each_entry_safe(node, n, &priv->iommu_list, list) {
- params.gem_obj = node->gem_obj;
- exynos_drm_iommu_unmap_gem(&params, node->dma_addr,
- IOMMU_ROTATOR);
- list_del(&node->list);
- kfree(node);
- node = NULL;
+ if (cmd != IPP_CMD_M2M) {
+ DRM_ERROR("not support cmd: %d\n", cmd);
+ return -EINVAL;
}
- kfree(priv);
+ /* Set interrupt enable */
+ rotator_reg_set_irq(rot, true);
+
+ /* start rotator operation */
+ rotator_reg_set_start(rot);
- return;
+ return 0;
}
static int __devinit rotator_probe(struct platform_device *pdev)
@@ -677,7 +669,7 @@ static int __devinit rotator_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct rot_context *rot;
struct resource *res;
- struct exynos_drm_subdrv *subdrv;
+ struct exynos_drm_ippdrv *ippdrv;
int ret;
rot = kzalloc(sizeof(*rot), GFP_KERNEL);
@@ -689,21 +681,6 @@ static int __devinit rotator_probe(struct platform_device *pdev)
rot->limit_tbl = (struct rot_limit_table *)
platform_get_device_id(pdev)->driver_data;
- mutex_init(&rot->exec_mutex);
- spin_lock_init(&rot->irq_lock);
-
- ret = exynos_drm_iommu_setup(dev);
- if (ret < 0) {
- dev_err(dev, "failed to setup iommu\n");
- goto err_iommu_setup;
- }
-
- ret = exynos_drm_iommu_activate(dev);
- if (ret < 0) {
- dev_err(dev, "failed to activate iommu\n");
- goto err_iommu_activate;
- }
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "failed to find registers\n");
@@ -733,7 +710,7 @@ static int __devinit rotator_probe(struct platform_device *pdev)
goto err_get_irq;
}
- ret = request_threaded_irq(rot->irq, NULL, rotator_irq_thread,
+ ret = request_threaded_irq(rot->irq, NULL, rotator_irq_handler,
IRQF_ONESHOT, "drm_rotator", rot);
if (ret < 0) {
dev_err(dev, "failed to request irq\n");
@@ -748,26 +725,28 @@ static int __devinit rotator_probe(struct platform_device *pdev)
}
pm_runtime_enable(dev);
- pm_qos_add_request(&rot->pm_qos, PM_QOS_BUS_DMA_THROUGHPUT, 0);
- subdrv = &rot->subdrv;
- subdrv->dev = dev;
- subdrv->open = rotator_subdrv_open;
- subdrv->close = rotator_subdrv_close;
+ ippdrv = &rot->ippdrv;
+ ippdrv->dev = dev;
+ ippdrv->iommu_used = true;
+ ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &rot_src_ops;
+ ippdrv->ops[EXYNOS_DRM_OPS_DST] = &rot_dst_ops;
+ ippdrv->check_property = rotator_ippdrv_check_property;
+ ippdrv->start = rotator_ippdrv_start;
platform_set_drvdata(pdev, rot);
- ret = exynos_drm_subdrv_register(subdrv);
+ ret = exynos_drm_ippdrv_register(ippdrv);
if (ret < 0) {
dev_err(dev, "failed to register drm rotator device\n");
- goto err_subdrv_register;
+ goto err_ippdrv_register;
}
dev_info(dev, "The exynos rotator is probed successfully\n");
return 0;
-err_subdrv_register:
+err_ippdrv_register:
pm_runtime_disable(dev);
clk_put(rot->clock);
err_clk_get:
@@ -778,23 +757,18 @@ err_ioremap:
release_resource(rot->regs_res);
kfree(rot->regs_res);
err_get_resource:
- exynos_drm_iommu_deactivate(dev);
-err_iommu_activate:
- exynos_drm_iommu_cleanup(dev);
-err_iommu_setup:
kfree(rot);
return ret;
}
static int __devexit rotator_remove(struct platform_device *pdev)
{
- struct rot_context *rot = platform_get_drvdata(pdev);
-
- pm_qos_remove_request(&rot->pm_qos);
+ struct device *dev = &pdev->dev;
+ struct rot_context *rot = dev_get_drvdata(dev);
- exynos_drm_subdrv_unregister(&rot->subdrv);
+ exynos_drm_ippdrv_unregister(&rot->ippdrv);
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_disable(dev);
clk_put(rot->clock);
free_irq(rot->irq, rot);
@@ -804,9 +778,6 @@ static int __devexit rotator_remove(struct platform_device *pdev)
release_resource(rot->regs_res);
kfree(rot->regs_res);
- exynos_drm_iommu_deactivate(&pdev->dev);
- exynos_drm_iommu_cleanup(&pdev->dev);
-
kfree(rot);
return 0;
@@ -841,14 +812,13 @@ struct platform_device_id rotator_driver_ids[] = {
static int rotator_suspend(struct device *dev)
{
struct rot_context *rot = dev_get_drvdata(dev);
-
- /* Check & wait for running state */
- mutex_lock(&rot->exec_mutex);
- mutex_unlock(&rot->exec_mutex);
+ struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
+ struct drm_device *drm_dev = ippdrv->drm_dev;
+ struct exynos_drm_private *drm_priv = drm_dev->dev_private;
rot->suspended = true;
- exynos_drm_iommu_deactivate(dev);
+ exynos_drm_iommu_deactivate(drm_priv->vmm, dev);
return 0;
}
@@ -856,12 +826,18 @@ static int rotator_suspend(struct device *dev)
static int rotator_resume(struct device *dev)
{
struct rot_context *rot = dev_get_drvdata(dev);
+ struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
+ struct drm_device *drm_dev = ippdrv->drm_dev;
+ struct exynos_drm_private *drm_priv = drm_dev->dev_private;
+ int ret;
- rot->suspended = false;
+ ret = exynos_drm_iommu_activate(drm_priv->vmm, dev);
+ if (ret)
+ DRM_ERROR("failed to activate iommu\n");
- exynos_drm_iommu_activate(dev);
+ rot->suspended = false;
- return 0;
+ return ret;
}
#endif
@@ -880,7 +856,6 @@ static int rotator_runtime_resume(struct device *dev)
struct rot_context *rot = dev_get_drvdata(dev);
clk_enable(rot->clock);
- pm_qos_update_request(&rot->pm_qos, 400000);
return 0;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.h b/drivers/gpu/drm/exynos/exynos_drm_rotator.h
index 5f383d5..fe929c9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.h
@@ -10,16 +10,4 @@
#ifndef _EXYNOS_DRM_ROTATOR_H_
#define _EXYNOS_DRM_ROTATOR_H_
-#ifdef CONFIG_DRM_EXYNOS_ROTATOR
-extern int exynos_drm_rotator_exec_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-#else
-static inline int exynos_drm_rotator_exec_ioctl(struct drm_device *dev,
- void *data,
- struct drm_file *file_priv)
-{
- return -ENOTTY;
-}
-#endif
-
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ump.c b/drivers/gpu/drm/exynos/exynos_drm_ump.c
index fd9ba2a..f92759f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ump.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ump.c
@@ -85,7 +85,7 @@ static int exynos_drm_ump_add_buffer(void *obj,
* physically continuous buffer so let a ump descriptor
* have one buffer address.
*/
- ump_mem_desc[0].addr = (unsigned long)buf->dma_addr;
+ ump_mem_desc[0].addr = (unsigned long)buf->paddr;
ump_mem_desc[0].size = buf->size;
}
@@ -115,13 +115,6 @@ static int exynos_drm_ump_add_buffer(void *obj,
static void exynos_drm_ump_release_buffer(unsigned int handle)
{
DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!handle) {
- DRM_DEBUG_KMS("invalid ump handle.\n");
- return;
- }
-
- ump_dd_reference_release((ump_dd_handle)handle);
}
static struct exynos_drm_private_cb ump_callback = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 876e460..44bcdc8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -468,7 +468,7 @@ static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
return 0;
}
-static void vidi_subdrv_remove(struct drm_device *drm_dev)
+static void vidi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
{
DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -549,6 +549,8 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
struct exynos_drm_manager *manager;
struct exynos_drm_display_ops *display_ops;
struct drm_exynos_vidi_connection *vidi = data;
+ struct edid *raw_edid;
+ int edid_len;
DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -557,11 +559,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
return -EINVAL;
}
- if (!vidi->edid) {
- DRM_DEBUG_KMS("edid data is null.\n");
- return -EINVAL;
- }
-
if (vidi->connection > 1) {
DRM_DEBUG_KMS("connection should be 0 or 1.\n");
return -EINVAL;
@@ -588,8 +585,23 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
return -EINVAL;
}
- if (vidi->connection)
- ctx->raw_edid = (struct edid *)vidi->edid;
+ if (vidi->connection) {
+ if (!vidi->edid) {
+ DRM_DEBUG_KMS("edid data is null.\n");
+ return -EINVAL;
+ }
+ raw_edid = (struct edid *)vidi->edid;
+ edid_len = (1 + raw_edid->extensions) * EDID_LENGTH;
+ ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL);
+ if (!ctx->raw_edid) {
+ DRM_DEBUG_KMS("failed to allocate raw_edid.\n");
+ return -ENOMEM;
+ }
+ memcpy(ctx->raw_edid, raw_edid, edid_len);
+ } else {
+ kfree(ctx->raw_edid);
+ ctx->raw_edid = NULL;
+ }
ctx->connected = vidi->connection;
drm_helper_hpd_irq_event(ctx->subdrv.drm_dev);
@@ -644,6 +656,7 @@ static int __devexit vidi_remove(struct platform_device *pdev)
exynos_drm_subdrv_unregister(&ctx->subdrv);
+ kfree(ctx->raw_edid);
kfree(ctx);
return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 0c44cb7..48d7f98 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -37,6 +37,7 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_hdmi.h"
+#include "exynos_drm_iommu.h"
#include "exynos_hdmi.h"
@@ -61,6 +62,7 @@ struct hdmi_context {
bool powered;
bool is_v13;
bool dvi_mode;
+ bool iommu_on;
struct mutex hdmi_mutex;
struct resource *regs_res;
@@ -927,8 +929,6 @@ static const struct hdmi_conf hdmi_confs[] = {
{ 720, 480, 60, false, hdmiphy_conf27_027, &hdmi_conf_480p60 },
{ 1280, 720, 50, false, hdmiphy_conf74_25, &hdmi_conf_720p50 },
{ 1280, 720, 60, false, hdmiphy_conf74_25, &hdmi_conf_720p60 },
- { 1920, 1080, 50, true, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
- { 1920, 1080, 60, true, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
{ 1920, 1080, 30, false, hdmiphy_conf74_176, &hdmi_conf_1080p30 },
};
@@ -1838,6 +1838,104 @@ static void hdmi_timing_apply(struct hdmi_context *hdata)
hdmi_v14_timing_apply(hdata);
}
+static int hdmi_phy_ctrl(struct i2c_client *client, u8 reg, u8 bit,
+ u8 *read_buffer, bool enable)
+{
+ int ret;
+ u8 operation[2];
+
+ operation[0] = reg;
+ operation[1] = enable ? (read_buffer[reg] & (~(1 << bit))) :
+ (read_buffer[reg] | (1 << bit));
+ read_buffer[reg] = operation[1];
+
+ ret = i2c_master_send(client, operation, 2);
+ if (ret != 2) {
+ DRM_ERROR("failed to turn %s HDMIPHY via I2C\n",
+ enable ? "enable" : "disable");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int hdmi_phy_power_ctrl(struct hdmi_context *hdata, bool enable)
+{
+ struct hdmi_resources *res = &hdata->res;
+ u8 operation[2];
+ u8 read_buffer[32];
+ int ret = 0, i;
+
+ DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
+
+ clk_enable(res->hdmiphy);
+
+ /* read full register */
+ operation[0] = 0x1;
+ i2c_master_send(hdata->hdmiphy_port, operation, 1);
+
+ memset(read_buffer, 0x0, sizeof(read_buffer));
+ ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
+ if (ret < 0) {
+ DRM_ERROR("failed to read hdmiphy config\n");
+ goto err_clear;
+ }
+
+ for (i = 0; i < ret; i++)
+ DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
+ "recv [0x%02x]\n", i, operation[i], read_buffer[i]);
+
+ /* ocspad control */
+ operation[0] = 0x0b;
+ if (enable)
+ operation[1] = 0xd8;
+ else
+ operation[1] = 0x18;
+ read_buffer[0x0b] = operation[1];
+
+ ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
+ if (ret != 2) {
+ DRM_ERROR("failed to %s osc pad\n",
+ enable ? "enable" : "disable");
+ goto err_clear;
+ }
+
+ hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x7, read_buffer, enable);
+ hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x0, read_buffer, enable);
+ hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x1, read_buffer, enable);
+ hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x2, read_buffer, enable);
+ hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x4, read_buffer, enable);
+ hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x5, read_buffer, enable);
+ hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x6, read_buffer, enable);
+
+ if (!enable)
+ hdmi_phy_ctrl(hdata->hdmiphy_port, 0x4, 0x3, read_buffer, 0);
+
+ /* read full register */
+ operation[0] = 0x1;
+ i2c_master_send(hdata->hdmiphy_port, operation, 1);
+
+ memset(read_buffer, 0x0, sizeof(read_buffer));
+ ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
+ if (ret < 0) {
+ DRM_ERROR("failed to read hdmiphy config\n");
+ goto err_clear;
+ }
+
+ for (i = 0; i < ret; i++)
+ DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
+ "recv [0x%02x]\n", i, operation[i], read_buffer[i]);
+
+ clk_disable(res->hdmiphy);
+
+ return 0;
+
+err_clear:
+ clk_disable(res->hdmiphy);
+
+ return ret;
+}
+
static void hdmiphy_conf_reset(struct hdmi_context *hdata)
{
u8 buffer[2];
@@ -2003,15 +2101,46 @@ static void hdmi_get_max_resol(void *ctx, unsigned int *width,
static void hdmi_commit(void *ctx)
{
struct hdmi_context *hdata = ctx;
+ struct exynos_drm_private *drm_priv;
+ struct exynos_drm_hdmi_context *drm_hdmi_ctx;
+ struct drm_device *drm_dev;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
hdmi_conf_apply(hdata);
+
+ /*
+ * parent_ctx is created at hdmi_probe() and
+ * parent_ctx->drm_dev is set at hdmi_subdrv_probe()
+ */
+ drm_hdmi_ctx = hdata->parent_ctx;
+ drm_dev = drm_hdmi_ctx->drm_dev;
+ if (drm_dev)
+ drm_priv = drm_dev->dev_private;
+ else
+ return;
+
+ /*
+ * if iommu support for exynos drm was enabled, this function is
+ * called first time(!hdata->iommu_on) then enable iommu unit.
+ */
+ if (drm_priv->vmm && !hdata->iommu_on) {
+ int ret;
+
+ ret = exynos_drm_iommu_activate(drm_priv->vmm, hdata->dev);
+ if (ret < 0) {
+ DRM_ERROR("failed to activate iommu.\n");
+ return;
+ }
+
+ hdata->iommu_on = true;
+ }
}
static void hdmi_poweron(struct hdmi_context *hdata)
{
struct hdmi_resources *res = &hdata->res;
+ int ret;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -2029,6 +2158,32 @@ static void hdmi_poweron(struct hdmi_context *hdata)
pm_runtime_get_sync(hdata->dev);
+ ret = hdmi_phy_power_ctrl(hdata, true);
+ if (ret) {
+ DRM_ERROR("failed to control phy power\n");
+ return;
+ }
+
+ if (hdata->iommu_on) {
+ struct exynos_drm_private *drm_priv;
+ struct exynos_drm_hdmi_context *drm_hdmi_ctx;
+ struct drm_device *drm_dev;
+
+ drm_hdmi_ctx = hdata->parent_ctx;
+ drm_dev = drm_hdmi_ctx->drm_dev;
+
+ if (drm_dev)
+ drm_priv = drm_dev->dev_private;
+ else
+ return;
+
+ ret = exynos_drm_iommu_activate(drm_priv->vmm, hdata->dev);
+ if (ret < 0) {
+ DRM_ERROR("failed to activate iommu.\n");
+ return;
+ }
+ }
+
regulator_bulk_enable(res->regul_count, res->regul_bulk);
clk_enable(res->hdmiphy);
clk_enable(res->hdmi);
@@ -2038,6 +2193,7 @@ static void hdmi_poweron(struct hdmi_context *hdata)
static void hdmi_poweroff(struct hdmi_context *hdata)
{
struct hdmi_resources *res = &hdata->res;
+ int ret;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -2057,16 +2213,48 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
clk_disable(res->hdmiphy);
regulator_bulk_disable(res->regul_count, res->regul_bulk);
- pm_runtime_put_sync(hdata->dev);
-
mutex_lock(&hdata->hdmi_mutex);
if (hdata->cfg_hpd)
hdata->cfg_hpd(false);
+ ret = hdmi_phy_power_ctrl(hdata, false);
+ if (ret) {
+ DRM_ERROR("failed to control phy power\n");
+ return;
+ }
+
+ if (hdata->iommu_on) {
+ struct exynos_drm_private *drm_priv;
+ struct exynos_drm_hdmi_context *drm_hdmi_ctx;
+ struct drm_device *drm_dev;
+
+ drm_hdmi_ctx = hdata->parent_ctx;
+ drm_dev = drm_hdmi_ctx->drm_dev;
+ if (drm_dev)
+ drm_priv = drm_dev->dev_private;
+ else {
+ if (hdata->cfg_hpd)
+ hdata->cfg_hpd(true);
+
+ regulator_bulk_enable(res->regul_count,
+ res->regul_bulk);
+
+ clk_enable(res->hdmiphy);
+ clk_enable(res->hdmi);
+ clk_enable(res->sclk_hdmi);
+
+ mutex_unlock(&hdata->hdmi_mutex);
+ return;
+ }
+
+ exynos_drm_iommu_deactivate(drm_priv->vmm, hdata->dev);
+ }
+
hdata->powered = false;
out:
mutex_unlock(&hdata->hdmi_mutex);
+ pm_runtime_put_sync(hdata->dev);
}
static void hdmi_dpms(void *ctx, int mode)
@@ -2350,6 +2538,17 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
hdata->hdmiphy_port = hdmi_hdmiphy;
+ /*
+ * HDMI PHY power off
+ * HDMI PHY is on as default configuration
+ * So, HDMI PHY must be turned off if it's not used
+ */
+ ret = hdmi_phy_power_ctrl(hdata, false);
+ if (ret) {
+ DRM_ERROR("failed to control phy power\n");
+ goto err_hdmiphy;
+ }
+
hdata->external_irq = platform_get_irq_byname(pdev, "external_irq");
if (hdata->external_irq < 0) {
DRM_ERROR("failed to get platform irq\n");
@@ -2435,6 +2634,7 @@ static int __devexit hdmi_remove(struct platform_device *pdev)
i2c_del_driver(&ddc_driver);
kfree(hdata);
+ kfree(ctx);
return 0;
}
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 68ef010..206cbbc 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -601,18 +601,20 @@ static void mixer_win_reset(struct mixer_context *ctx)
mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
/* setting graphical layers */
-
val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
val |= MXR_GRP_CFG_WIN_BLEND_EN;
+ val |= MXR_GRP_CFG_BLEND_PRE_MUL;
+ val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
/* the same configuration for both layers */
mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
-
- val |= MXR_GRP_CFG_BLEND_PRE_MUL;
- val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
+ /* setting video layers */
+ val = MXR_GRP_CFG_ALPHA_VAL(0);
+ mixer_reg_write(res, MXR_VIDEO_CFG, val);
+
/* configuration of Video Processor Registers */
vp_win_reset(ctx);
vp_default_filter(res);
diff --git a/drivers/gpu/drm/exynos/regs-fimc.h b/drivers/gpu/drm/exynos/regs-fimc.h
new file mode 100644
index 0000000..be014b3
--- /dev/null
+++ b/drivers/gpu/drm/exynos/regs-fimc.h
@@ -0,0 +1,669 @@
+/* drivers/gpu/drm/exynos/regs-fimc.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Register definition file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef SAMSUNG_REGS_FIMC_H
+#define SAMSUNG_REGS_FIMC_H
+
+/*
+ * Register part
+*/
+/* Input source format */
+#define EXYNOS_CISRCFMT (0x00)
+/* Window offset */
+#define EXYNOS_CIWDOFST (0x04)
+/* Global control */
+#define EXYNOS_CIGCTRL (0x08)
+/* Window offset 2 */
+#define EXYNOS_CIWDOFST2 (0x14)
+/* Y 1st frame start address for output DMA */
+#define EXYNOS_CIOYSA1 (0x18)
+/* Y 2nd frame start address for output DMA */
+#define EXYNOS_CIOYSA2 (0x1c)
+/* Y 3rd frame start address for output DMA */
+#define EXYNOS_CIOYSA3 (0x20)
+/* Y 4th frame start address for output DMA */
+#define EXYNOS_CIOYSA4 (0x24)
+/* Cb 1st frame start address for output DMA */
+#define EXYNOS_CIOCBSA1 (0x28)
+/* Cb 2nd frame start address for output DMA */
+#define EXYNOS_CIOCBSA2 (0x2c)
+/* Cb 3rd frame start address for output DMA */
+#define EXYNOS_CIOCBSA3 (0x30)
+/* Cb 4th frame start address for output DMA */
+#define EXYNOS_CIOCBSA4 (0x34)
+/* Cr 1st frame start address for output DMA */
+#define EXYNOS_CIOCRSA1 (0x38)
+/* Cr 2nd frame start address for output DMA */
+#define EXYNOS_CIOCRSA2 (0x3c)
+/* Cr 3rd frame start address for output DMA */
+#define EXYNOS_CIOCRSA3 (0x40)
+/* Cr 4th frame start address for output DMA */
+#define EXYNOS_CIOCRSA4 (0x44)
+/* Target image format */
+#define EXYNOS_CITRGFMT (0x48)
+/* Output DMA control */
+#define EXYNOS_CIOCTRL (0x4c)
+/* Pre-scaler control 1 */
+#define EXYNOS_CISCPRERATIO (0x50)
+/* Pre-scaler control 2 */
+#define EXYNOS_CISCPREDST (0x54)
+/* Main scaler control */
+#define EXYNOS_CISCCTRL (0x58)
+/* Target area */
+#define EXYNOS_CITAREA (0x5c)
+/* Status */
+#define EXYNOS_CISTATUS (0x64)
+/* Status2 */
+#define EXYNOS_CISTATUS2 (0x68)
+/* Image capture enable command */
+#define EXYNOS_CIIMGCPT (0xc0)
+/* Capture sequence */
+#define EXYNOS_CICPTSEQ (0xc4)
+/* Image effects */
+#define EXYNOS_CIIMGEFF (0xd0)
+/* Y frame start address for input DMA */
+#define EXYNOS_CIIYSA0 (0xd4)
+/* Cb frame start address for input DMA */
+#define EXYNOS_CIICBSA0 (0xd8)
+/* Cr frame start address for input DMA */
+#define EXYNOS_CIICRSA0 (0xdc)
+/* Input DMA Y Line Skip */
+#define EXYNOS_CIILINESKIP_Y (0xec)
+/* Input DMA Cb Line Skip */
+#define EXYNOS_CIILINESKIP_CB (0xf0)
+/* Input DMA Cr Line Skip */
+#define EXYNOS_CIILINESKIP_CR (0xf4)
+/* Real input DMA image size */
+#define EXYNOS_CIREAL_ISIZE (0xf8)
+/* Input DMA control */
+#define EXYNOS_MSCTRL (0xfc)
+/* Y frame start address for input DMA */
+#define EXYNOS_CIIYSA1 (0x144)
+/* Cb frame start address for input DMA */
+#define EXYNOS_CIICBSA1 (0x148)
+/* Cr frame start address for input DMA */
+#define EXYNOS_CIICRSA1 (0x14c)
+/* Output DMA Y offset */
+#define EXYNOS_CIOYOFF (0x168)
+/* Output DMA CB offset */
+#define EXYNOS_CIOCBOFF (0x16c)
+/* Output DMA CR offset */
+#define EXYNOS_CIOCROFF (0x170)
+/* Input DMA Y offset */
+#define EXYNOS_CIIYOFF (0x174)
+/* Input DMA CB offset */
+#define EXYNOS_CIICBOFF (0x178)
+/* Input DMA CR offset */
+#define EXYNOS_CIICROFF (0x17c)
+/* Input DMA original image size */
+#define EXYNOS_ORGISIZE (0x180)
+/* Output DMA original image size */
+#define EXYNOS_ORGOSIZE (0x184)
+/* Real output DMA image size */
+#define EXYNOS_CIEXTEN (0x188)
+/* DMA parameter */
+#define EXYNOS_CIDMAPARAM (0x18c)
+/* MIPI CSI image format */
+#define EXYNOS_CSIIMGFMT (0x194)
+/* FIMC Clock Source Select */
+#define EXYNOS_MISC_FIMC (0x198)
+
+/* Add for FIMC v5.1 */
+/* Output Frame Buffer Sequence */
+#define EXYNOS_CIFCNTSEQ (0x1fc)
+/* Y 5th frame start address for output DMA */
+#define EXYNOS_CIOYSA5 (0x200)
+/* Y 6th frame start address for output DMA */
+#define EXYNOS_CIOYSA6 (0x204)
+/* Y 7th frame start address for output DMA */
+#define EXYNOS_CIOYSA7 (0x208)
+/* Y 8th frame start address for output DMA */
+#define EXYNOS_CIOYSA8 (0x20c)
+/* Y 9th frame start address for output DMA */
+#define EXYNOS_CIOYSA9 (0x210)
+/* Y 10th frame start address for output DMA */
+#define EXYNOS_CIOYSA10 (0x214)
+/* Y 11th frame start address for output DMA */
+#define EXYNOS_CIOYSA11 (0x218)
+/* Y 12th frame start address for output DMA */
+#define EXYNOS_CIOYSA12 (0x21c)
+/* Y 13th frame start address for output DMA */
+#define EXYNOS_CIOYSA13 (0x220)
+/* Y 14th frame start address for output DMA */
+#define EXYNOS_CIOYSA14 (0x224)
+/* Y 15th frame start address for output DMA */
+#define EXYNOS_CIOYSA15 (0x228)
+/* Y 16th frame start address for output DMA */
+#define EXYNOS_CIOYSA16 (0x22c)
+/* Y 17th frame start address for output DMA */
+#define EXYNOS_CIOYSA17 (0x230)
+/* Y 18th frame start address for output DMA */
+#define EXYNOS_CIOYSA18 (0x234)
+/* Y 19th frame start address for output DMA */
+#define EXYNOS_CIOYSA19 (0x238)
+/* Y 20th frame start address for output DMA */
+#define EXYNOS_CIOYSA20 (0x23c)
+/* Y 21th frame start address for output DMA */
+#define EXYNOS_CIOYSA21 (0x240)
+/* Y 22th frame start address for output DMA */
+#define EXYNOS_CIOYSA22 (0x244)
+/* Y 23th frame start address for output DMA */
+#define EXYNOS_CIOYSA23 (0x248)
+/* Y 24th frame start address for output DMA */
+#define EXYNOS_CIOYSA24 (0x24c)
+/* Y 25th frame start address for output DMA */
+#define EXYNOS_CIOYSA25 (0x250)
+/* Y 26th frame start address for output DMA */
+#define EXYNOS_CIOYSA26 (0x254)
+/* Y 27th frame start address for output DMA */
+#define EXYNOS_CIOYSA27 (0x258)
+/* Y 28th frame start address for output DMA */
+#define EXYNOS_CIOYSA28 (0x25c)
+/* Y 29th frame start address for output DMA */
+#define EXYNOS_CIOYSA29 (0x260)
+/* Y 30th frame start address for output DMA */
+#define EXYNOS_CIOYSA30 (0x264)
+/* Y 31th frame start address for output DMA */
+#define EXYNOS_CIOYSA31 (0x268)
+/* Y 32th frame start address for output DMA */
+#define EXYNOS_CIOYSA32 (0x26c)
+
+/* CB 5th frame start address for output DMA */
+#define EXYNOS_CIOCBSA5 (0x270)
+/* CB 6th frame start address for output DMA */
+#define EXYNOS_CIOCBSA6 (0x274)
+/* CB 7th frame start address for output DMA */
+#define EXYNOS_CIOCBSA7 (0x278)
+/* CB 8th frame start address for output DMA */
+#define EXYNOS_CIOCBSA8 (0x27c)
+/* CB 9th frame start address for output DMA */
+#define EXYNOS_CIOCBSA9 (0x280)
+/* CB 10th frame start address for output DMA */
+#define EXYNOS_CIOCBSA10 (0x284)
+/* CB 11th frame start address for output DMA */
+#define EXYNOS_CIOCBSA11 (0x288)
+/* CB 12th frame start address for output DMA */
+#define EXYNOS_CIOCBSA12 (0x28c)
+/* CB 13th frame start address for output DMA */
+#define EXYNOS_CIOCBSA13 (0x290)
+/* CB 14th frame start address for output DMA */
+#define EXYNOS_CIOCBSA14 (0x294)
+/* CB 15th frame start address for output DMA */
+#define EXYNOS_CIOCBSA15 (0x298)
+/* CB 16th frame start address for output DMA */
+#define EXYNOS_CIOCBSA16 (0x29c)
+/* CB 17th frame start address for output DMA */
+#define EXYNOS_CIOCBSA17 (0x2a0)
+/* CB 18th frame start address for output DMA */
+#define EXYNOS_CIOCBSA18 (0x2a4)
+/* CB 19th frame start address for output DMA */
+#define EXYNOS_CIOCBSA19 (0x2a8)
+/* CB 20th frame start address for output DMA */
+#define EXYNOS_CIOCBSA20 (0x2ac)
+/* CB 21th frame start address for output DMA */
+#define EXYNOS_CIOCBSA21 (0x2b0)
+/* CB 22th frame start address for output DMA */
+#define EXYNOS_CIOCBSA22 (0x2b4)
+/* CB 23th frame start address for output DMA */
+#define EXYNOS_CIOCBSA23 (0x2b8)
+/* CB 24th frame start address for output DMA */
+#define EXYNOS_CIOCBSA24 (0x2bc)
+/* CB 25th frame start address for output DMA */
+#define EXYNOS_CIOCBSA25 (0x2c0)
+/* CB 26th frame start address for output DMA */
+#define EXYNOS_CIOCBSA26 (0x2c4)
+/* CB 27th frame start address for output DMA */
+#define EXYNOS_CIOCBSA27 (0x2c8)
+/* CB 28th frame start address for output DMA */
+#define EXYNOS_CIOCBSA28 (0x2cc)
+/* CB 29th frame start address for output DMA */
+#define EXYNOS_CIOCBSA29 (0x2d0)
+/* CB 30th frame start address for output DMA */
+#define EXYNOS_CIOCBSA30 (0x2d4)
+/* CB 31th frame start address for output DMA */
+#define EXYNOS_CIOCBSA31 (0x2d8)
+/* CB 32th frame start address for output DMA */
+#define EXYNOS_CIOCBSA32 (0x2dc)
+
+/* CR 5th frame start address for output DMA */
+#define EXYNOS_CIOCRSA5 (0x2e0)
+/* CR 6th frame start address for output DMA */
+#define EXYNOS_CIOCRSA6 (0x2e4)
+/* CR 7th frame start address for output DMA */
+#define EXYNOS_CIOCRSA7 (0x2e8)
+/* CR 8th frame start address for output DMA */
+#define EXYNOS_CIOCRSA8 (0x2ec)
+/* CR 9th frame start address for output DMA */
+#define EXYNOS_CIOCRSA9 (0x2f0)
+/* CR 10th frame start address for output DMA */
+#define EXYNOS_CIOCRSA10 (0x2f4)
+/* CR 11th frame start address for output DMA */
+#define EXYNOS_CIOCRSA11 (0x2f8)
+/* CR 12th frame start address for output DMA */
+#define EXYNOS_CIOCRSA12 (0x2fc)
+/* CR 13th frame start address for output DMA */
+#define EXYNOS_CIOCRSA13 (0x300)
+/* CR 14th frame start address for output DMA */
+#define EXYNOS_CIOCRSA14 (0x304)
+/* CR 15th frame start address for output DMA */
+#define EXYNOS_CIOCRSA15 (0x308)
+/* CR 16th frame start address for output DMA */
+#define EXYNOS_CIOCRSA16 (0x30c)
+/* CR 17th frame start address for output DMA */
+#define EXYNOS_CIOCRSA17 (0x310)
+/* CR 18th frame start address for output DMA */
+#define EXYNOS_CIOCRSA18 (0x314)
+/* CR 19th frame start address for output DMA */
+#define EXYNOS_CIOCRSA19 (0x318)
+/* CR 20th frame start address for output DMA */
+#define EXYNOS_CIOCRSA20 (0x31c)
+/* CR 21th frame start address for output DMA */
+#define EXYNOS_CIOCRSA21 (0x320)
+/* CR 22th frame start address for output DMA */
+#define EXYNOS_CIOCRSA22 (0x324)
+/* CR 23th frame start address for output DMA */
+#define EXYNOS_CIOCRSA23 (0x328)
+/* CR 24th frame start address for output DMA */
+#define EXYNOS_CIOCRSA24 (0x32c)
+/* CR 25th frame start address for output DMA */
+#define EXYNOS_CIOCRSA25 (0x330)
+/* CR 26th frame start address for output DMA */
+#define EXYNOS_CIOCRSA26 (0x334)
+/* CR 27th frame start address for output DMA */
+#define EXYNOS_CIOCRSA27 (0x338)
+/* CR 28th frame start address for output DMA */
+#define EXYNOS_CIOCRSA28 (0x33c)
+/* CR 29th frame start address for output DMA */
+#define EXYNOS_CIOCRSA29 (0x340)
+/* CR 30th frame start address for output DMA */
+#define EXYNOS_CIOCRSA30 (0x344)
+/* CR 31th frame start address for output DMA */
+#define EXYNOS_CIOCRSA31 (0x348)
+/* CR 32th frame start address for output DMA */
+#define EXYNOS_CIOCRSA32 (0x34c)
+
+/*
+ * Macro part
+*/
+/* frame start address 1 ~ 4, 5 ~ 32 */
+/* Number of Default PingPong Memory */
+#define DEF_PP 4
+#define EXYNOS_CIOYSA(__x) \
+ (((__x) < DEF_PP) ? \
+ (EXYNOS_CIOYSA1 + (__x) * 4) : \
+ (EXYNOS_CIOYSA5 + ((__x) - DEF_PP) * 4))
+#define EXYNOS_CIOCBSA(__x) \
+ (((__x) < DEF_PP) ? \
+ (EXYNOS_CIOCBSA1 + (__x) * 4) : \
+ (EXYNOS_CIOCBSA5 + ((__x) - DEF_PP) * 4))
+#define EXYNOS_CIOCRSA(__x) \
+ (((__x) < DEF_PP) ? \
+ (EXYNOS_CIOCRSA1 + (__x) * 4) : \
+ (EXYNOS_CIOCRSA5 + ((__x) - DEF_PP) * 4))
+/* Number of Default PingPong Memory */
+#define DEF_IPP 1
+#define EXYNOS_CIIYSA(__x) \
+ (((__x) < DEF_IPP) ? \
+ (EXYNOS_CIIYSA0) : (EXYNOS_CIIYSA1))
+#define EXYNOS_CIICBSA(__x) \
+ (((__x) < DEF_IPP) ? \
+ (EXYNOS_CIICBSA0) : (EXYNOS_CIICBSA1))
+#define EXYNOS_CIICRSA(__x) \
+ (((__x) < DEF_IPP) ? \
+ (EXYNOS_CIICRSA0) : (EXYNOS_CIICRSA1))
+
+#define EXYNOS_CISRCFMT_SOURCEHSIZE(x) ((x) << 16)
+#define EXYNOS_CISRCFMT_SOURCEVSIZE(x) ((x) << 0)
+
+#define EXYNOS_CIWDOFST_WINHOROFST(x) ((x) << 16)
+#define EXYNOS_CIWDOFST_WINVEROFST(x) ((x) << 0)
+
+#define EXYNOS_CIWDOFST2_WINHOROFST2(x) ((x) << 16)
+#define EXYNOS_CIWDOFST2_WINVEROFST2(x) ((x) << 0)
+
+#define EXYNOS_CITRGFMT_TARGETHSIZE(x) (((x) & 0x1fff) << 16)
+#define EXYNOS_CITRGFMT_TARGETVSIZE(x) (((x) & 0x1fff) << 0)
+
+#define EXYNOS_CISCPRERATIO_SHFACTOR(x) ((x) << 28)
+#define EXYNOS_CISCPRERATIO_PREHORRATIO(x) ((x) << 16)
+#define EXYNOS_CISCPRERATIO_PREVERRATIO(x) ((x) << 0)
+
+#define EXYNOS_CISCPREDST_PREDSTWIDTH(x) ((x) << 16)
+#define EXYNOS_CISCPREDST_PREDSTHEIGHT(x) ((x) << 0)
+
+#define EXYNOS_CISCCTRL_MAINHORRATIO(x) ((x) << 16)
+#define EXYNOS_CISCCTRL_MAINVERRATIO(x) ((x) << 0)
+
+#define EXYNOS_CITAREA_TARGET_AREA(x) ((x) << 0)
+
+#define EXYNOS_CISTATUS_GET_FRAME_COUNT(x) (((x) >> 26) & 0x3)
+#define EXYNOS_CISTATUS_GET_FRAME_END(x) (((x) >> 17) & 0x1)
+#define EXYNOS_CISTATUS_GET_LAST_CAPTURE_END(x) (((x) >> 16) & 0x1)
+#define EXYNOS_CISTATUS_GET_LCD_STATUS(x) (((x) >> 9) & 0x1)
+#define EXYNOS_CISTATUS_GET_ENVID_STATUS(x) (((x) >> 8) & 0x1)
+
+#define EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(x) (((x) >> 7) & 0x3f)
+#define EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(x) ((x) & 0x3f)
+
+#define EXYNOS_CIIMGEFF_FIN(x) ((x & 0x7) << 26)
+#define EXYNOS_CIIMGEFF_PAT_CB(x) ((x) << 13)
+#define EXYNOS_CIIMGEFF_PAT_CR(x) ((x) << 0)
+
+#define EXYNOS_CIILINESKIP(x) (((x) & 0xf) << 24)
+
+#define EXYNOS_CIREAL_ISIZE_HEIGHT(x) ((x) << 16)
+#define EXYNOS_CIREAL_ISIZE_WIDTH(x) ((x) << 0)
+
+#define EXYNOS_MSCTRL_SUCCESSIVE_COUNT(x) ((x) << 24)
+#define EXYNOS_MSCTRL_GET_INDMA_STATUS(x) ((x) & 0x1)
+
+#define EXYNOS_CIOYOFF_VERTICAL(x) ((x) << 16)
+#define EXYNOS_CIOYOFF_HORIZONTAL(x) ((x) << 0)
+
+#define EXYNOS_CIOCBOFF_VERTICAL(x) ((x) << 16)
+#define EXYNOS_CIOCBOFF_HORIZONTAL(x) ((x) << 0)
+
+#define EXYNOS_CIOCROFF_VERTICAL(x) ((x) << 16)
+#define EXYNOS_CIOCROFF_HORIZONTAL(x) ((x) << 0)
+
+#define EXYNOS_CIIYOFF_VERTICAL(x) ((x) << 16)
+#define EXYNOS_CIIYOFF_HORIZONTAL(x) ((x) << 0)
+
+#define EXYNOS_CIICBOFF_VERTICAL(x) ((x) << 16)
+#define EXYNOS_CIICBOFF_HORIZONTAL(x) ((x) << 0)
+
+#define EXYNOS_CIICROFF_VERTICAL(x) ((x) << 16)
+#define EXYNOS_CIICROFF_HORIZONTAL(x) ((x) << 0)
+
+#define EXYNOS_ORGISIZE_VERTICAL(x) ((x) << 16)
+#define EXYNOS_ORGISIZE_HORIZONTAL(x) ((x) << 0)
+
+#define EXYNOS_ORGOSIZE_VERTICAL(x) ((x) << 16)
+#define EXYNOS_ORGOSIZE_HORIZONTAL(x) ((x) << 0)
+
+#define EXYNOS_CIEXTEN_TARGETH_EXT(x) ((((x) & 0x2000) >> 13) << 26)
+#define EXYNOS_CIEXTEN_TARGETV_EXT(x) ((((x) & 0x2000) >> 13) << 24)
+#define EXYNOS_CIEXTEN_MAINHORRATIO_EXT(x) (((x) & 0x3F) << 10)
+#define EXYNOS_CIEXTEN_MAINVERRATIO_EXT(x) ((x) & 0x3F)
+
+/*
+ * Bit definition part
+*/
+/* Source format register */
+#define EXYNOS_CISRCFMT_ITU601_8BIT (1 << 31)
+#define EXYNOS_CISRCFMT_ITU656_8BIT (0 << 31)
+#define EXYNOS_CISRCFMT_ITU601_16BIT (1 << 29)
+#define EXYNOS_CISRCFMT_ORDER422_YCBYCR (0 << 14)
+#define EXYNOS_CISRCFMT_ORDER422_YCRYCB (1 << 14)
+#define EXYNOS_CISRCFMT_ORDER422_CBYCRY (2 << 14)
+#define EXYNOS_CISRCFMT_ORDER422_CRYCBY (3 << 14)
+/* ITU601 16bit only */
+#define EXYNOS_CISRCFMT_ORDER422_Y4CBCRCBCR (0 << 14)
+/* ITU601 16bit only */
+#define EXYNOS_CISRCFMT_ORDER422_Y4CRCBCRCB (1 << 14)
+
+/* Window offset register */
+#define EXYNOS_CIWDOFST_WINOFSEN (1 << 31)
+#define EXYNOS_CIWDOFST_CLROVFIY (1 << 30)
+#define EXYNOS_CIWDOFST_CLROVRLB (1 << 29)
+#define EXYNOS_CIWDOFST_WINHOROFST_MASK (0x7ff << 16)
+#define EXYNOS_CIWDOFST_CLROVFICB (1 << 15)
+#define EXYNOS_CIWDOFST_CLROVFICR (1 << 14)
+#define EXYNOS_CIWDOFST_WINVEROFST_MASK (0xfff << 0)
+
+/* Global control register */
+#define EXYNOS_CIGCTRL_SWRST (1 << 31)
+#define EXYNOS_CIGCTRL_CAMRST_A (1 << 30)
+#define EXYNOS_CIGCTRL_SELCAM_ITU_B (0 << 29)
+#define EXYNOS_CIGCTRL_SELCAM_ITU_A (1 << 29)
+#define EXYNOS_CIGCTRL_SELCAM_ITU_MASK (1 << 29)
+#define EXYNOS_CIGCTRL_TESTPATTERN_NORMAL (0 << 27)
+#define EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR (1 << 27)
+#define EXYNOS_CIGCTRL_TESTPATTERN_HOR_INC (2 << 27)
+#define EXYNOS_CIGCTRL_TESTPATTERN_VER_INC (3 << 27)
+#define EXYNOS_CIGCTRL_TESTPATTERN_MASK (3 << 27)
+#define EXYNOS_CIGCTRL_TESTPATTERN_SHIFT (27)
+#define EXYNOS_CIGCTRL_INVPOLPCLK (1 << 26)
+#define EXYNOS_CIGCTRL_INVPOLVSYNC (1 << 25)
+#define EXYNOS_CIGCTRL_INVPOLHREF (1 << 24)
+#define EXYNOS_CIGCTRL_IRQ_OVFEN (1 << 22)
+#define EXYNOS_CIGCTRL_HREF_MASK (1 << 21)
+#define EXYNOS_CIGCTRL_IRQ_EDGE (0 << 20)
+#define EXYNOS_CIGCTRL_IRQ_LEVEL (1 << 20)
+#define EXYNOS_CIGCTRL_IRQ_CLR (1 << 19)
+#define EXYNOS_CIGCTRL_IRQ_END_DISABLE (1 << 18)
+#define EXYNOS_CIGCTRL_IRQ_DISABLE (0 << 16)
+#define EXYNOS_CIGCTRL_IRQ_ENABLE (1 << 16)
+#define EXYNOS_CIGCTRL_SHADOW_DISABLE (1 << 12)
+#define EXYNOS_CIGCTRL_CAM_JPEG (1 << 8)
+#define EXYNOS_CIGCTRL_SELCAM_MIPI_B (0 << 7)
+#define EXYNOS_CIGCTRL_SELCAM_MIPI_A (1 << 7)
+#define EXYNOS_CIGCTRL_SELCAM_MIPI_MASK (1 << 7)
+#define EXYNOS_CIGCTRL_SELWB_CAMIF_CAMERA (0 << 6)
+#define EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK (1 << 6)
+#define EXYNOS_CIGCTRL_SELWRITEBACK_MASK (1 << 10)
+#define EXYNOS_CIGCTRL_SELWRITEBACK_A (1 << 10)
+#define EXYNOS_CIGCTRL_SELWRITEBACK_B (0 << 10)
+#define EXYNOS_CIGCTRL_SELWB_CAMIF_MASK (1 << 6)
+#define EXYNOS_CIGCTRL_CSC_ITU601 (0 << 5)
+#define EXYNOS_CIGCTRL_CSC_ITU709 (1 << 5)
+#define EXYNOS_CIGCTRL_CSC_MASK (1 << 5)
+#define EXYNOS_CIGCTRL_INVPOLHSYNC (1 << 4)
+#define EXYNOS_CIGCTRL_SELCAM_FIMC_ITU (0 << 3)
+#define EXYNOS_CIGCTRL_SELCAM_FIMC_MIPI (1 << 3)
+#define EXYNOS_CIGCTRL_SELCAM_FIMC_MASK (1 << 3)
+#define EXYNOS_CIGCTRL_PROGRESSIVE (0 << 0)
+#define EXYNOS_CIGCTRL_INTERLACE (1 << 0)
+
+/* Window offset2 register */
+#define EXYNOS_CIWDOFST_WINHOROFST2_MASK (0xfff << 16)
+#define EXYNOS_CIWDOFST_WINVEROFST2_MASK (0xfff << 16)
+
+/* Target format register */
+#define EXYNOS_CITRGFMT_INROT90_CLOCKWISE (1 << 31)
+#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420 (0 << 29)
+#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422 (1 << 29)
+#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE (2 << 29)
+#define EXYNOS_CITRGFMT_OUTFORMAT_RGB (3 << 29)
+#define EXYNOS_CITRGFMT_OUTFORMAT_MASK (3 << 29)
+#define EXYNOS_CITRGFMT_FLIP_SHIFT (14)
+#define EXYNOS_CITRGFMT_FLIP_NORMAL (0 << 14)
+#define EXYNOS_CITRGFMT_FLIP_X_MIRROR (1 << 14)
+#define EXYNOS_CITRGFMT_FLIP_Y_MIRROR (2 << 14)
+#define EXYNOS_CITRGFMT_FLIP_180 (3 << 14)
+#define EXYNOS_CITRGFMT_FLIP_MASK (3 << 14)
+#define EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE (1 << 13)
+#define EXYNOS_CITRGFMT_TARGETV_MASK (0x1fff << 0)
+#define EXYNOS_CITRGFMT_TARGETH_MASK (0x1fff << 16)
+
+/* Output DMA control register */
+#define EXYNOS_CIOCTRL_WEAVE_OUT (1 << 31)
+#define EXYNOS_CIOCTRL_WEAVE_MASK (1 << 31)
+#define EXYNOS_CIOCTRL_LASTENDEN (1 << 30)
+#define EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR (0 << 24)
+#define EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB (1 << 24)
+#define EXYNOS_CIOCTRL_ORDER2P_MSB_CRCB (2 << 24)
+#define EXYNOS_CIOCTRL_ORDER2P_MSB_CBCR (3 << 24)
+#define EXYNOS_CIOCTRL_ORDER2P_SHIFT (24)
+#define EXYNOS_CIOCTRL_ORDER2P_MASK (3 << 24)
+#define EXYNOS_CIOCTRL_YCBCR_3PLANE (0 << 3)
+#define EXYNOS_CIOCTRL_YCBCR_2PLANE (1 << 3)
+#define EXYNOS_CIOCTRL_YCBCR_PLANE_MASK (1 << 3)
+#define EXYNOS_CIOCTRL_LASTIRQ_ENABLE (1 << 2)
+#define EXYNOS_CIOCTRL_ALPHA_OUT (0xff << 4)
+#define EXYNOS_CIOCTRL_ORDER422_YCBYCR (0 << 0)
+#define EXYNOS_CIOCTRL_ORDER422_YCRYCB (1 << 0)
+#define EXYNOS_CIOCTRL_ORDER422_CBYCRY (2 << 0)
+#define EXYNOS_CIOCTRL_ORDER422_CRYCBY (3 << 0)
+#define EXYNOS_CIOCTRL_ORDER422_MASK (3 << 0)
+
+/* Main scaler control register */
+#define EXYNOS_CISCCTRL_SCALERBYPASS (1 << 31)
+#define EXYNOS_CISCCTRL_SCALEUP_H (1 << 30)
+#define EXYNOS_CISCCTRL_SCALEUP_V (1 << 29)
+#define EXYNOS_CISCCTRL_CSCR2Y_NARROW (0 << 28)
+#define EXYNOS_CISCCTRL_CSCR2Y_WIDE (1 << 28)
+#define EXYNOS_CISCCTRL_CSCY2R_NARROW (0 << 27)
+#define EXYNOS_CISCCTRL_CSCY2R_WIDE (1 << 27)
+#define EXYNOS_CISCCTRL_LCDPATHEN_FIFO (1 << 26)
+#define EXYNOS_CISCCTRL_PROGRESSIVE (0 << 25)
+#define EXYNOS_CISCCTRL_INTERLACE (1 << 25)
+#define EXYNOS_CISCCTRL_SCAN_MASK (1 << 25)
+#define EXYNOS_CISCCTRL_SCALERSTART (1 << 15)
+#define EXYNOS_CISCCTRL_INRGB_FMT_RGB565 (0 << 13)
+#define EXYNOS_CISCCTRL_INRGB_FMT_RGB666 (1 << 13)
+#define EXYNOS_CISCCTRL_INRGB_FMT_RGB888 (2 << 13)
+#define EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK (3 << 13)
+#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11)
+#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11)
+#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11)
+#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK (3 << 11)
+#define EXYNOS_CISCCTRL_EXTRGB_NORMAL (0 << 10)
+#define EXYNOS_CISCCTRL_EXTRGB_EXTENSION (1 << 10)
+#define EXYNOS_CISCCTRL_ONE2ONE (1 << 9)
+#define EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK (0x1ff << 0)
+#define EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK (0x1ff << 16)
+
+/* Status register */
+#define EXYNOS_CISTATUS_OVFIY (1 << 31)
+#define EXYNOS_CISTATUS_OVFICB (1 << 30)
+#define EXYNOS_CISTATUS_OVFICR (1 << 29)
+#define EXYNOS_CISTATUS_VSYNC (1 << 28)
+#define EXYNOS_CISTATUS_SCALERSTART (1 << 26)
+#define EXYNOS_CISTATUS_WINOFSTEN (1 << 25)
+#define EXYNOS_CISTATUS_IMGCPTEN (1 << 22)
+#define EXYNOS_CISTATUS_IMGCPTENSC (1 << 21)
+#define EXYNOS_CISTATUS_VSYNC_A (1 << 20)
+#define EXYNOS_CISTATUS_VSYNC_B (1 << 19)
+#define EXYNOS_CISTATUS_OVRLB (1 << 18)
+#define EXYNOS_CISTATUS_FRAMEEND (1 << 17)
+#define EXYNOS_CISTATUS_LASTCAPTUREEND (1 << 16)
+#define EXYNOS_CISTATUS_VVALID_A (1 << 15)
+#define EXYNOS_CISTATUS_VVALID_B (1 << 14)
+
+/* Image capture enable register */
+#define EXYNOS_CIIMGCPT_IMGCPTEN (1 << 31)
+#define EXYNOS_CIIMGCPT_IMGCPTEN_SC (1 << 30)
+#define EXYNOS_CIIMGCPT_CPT_FREN_ENABLE (1 << 25)
+#define EXYNOS_CIIMGCPT_CPT_FRMOD_EN (0 << 18)
+#define EXYNOS_CIIMGCPT_CPT_FRMOD_CNT (1 << 18)
+
+/* Image effects register */
+#define EXYNOS_CIIMGEFF_IE_DISABLE (0 << 30)
+#define EXYNOS_CIIMGEFF_IE_ENABLE (1 << 30)
+#define EXYNOS_CIIMGEFF_IE_SC_BEFORE (0 << 29)
+#define EXYNOS_CIIMGEFF_IE_SC_AFTER (1 << 29)
+#define EXYNOS_CIIMGEFF_FIN_BYPASS (0 << 26)
+#define EXYNOS_CIIMGEFF_FIN_ARBITRARY (1 << 26)
+#define EXYNOS_CIIMGEFF_FIN_NEGATIVE (2 << 26)
+#define EXYNOS_CIIMGEFF_FIN_ARTFREEZE (3 << 26)
+#define EXYNOS_CIIMGEFF_FIN_EMBOSSING (4 << 26)
+#define EXYNOS_CIIMGEFF_FIN_SILHOUETTE (5 << 26)
+#define EXYNOS_CIIMGEFF_FIN_MASK (7 << 26)
+#define EXYNOS_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff < 0))
+
+/* Real input DMA size register */
+#define EXYNOS_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31)
+#define EXYNOS_CIREAL_ISIZE_ADDR_CH_DISABLE (1 << 30)
+#define EXYNOS_CIREAL_ISIZE_HEIGHT_MASK (0x3FFF << 16)
+#define EXYNOS_CIREAL_ISIZE_WIDTH_MASK (0x3FFF << 0)
+
+/* Input DMA control register */
+#define EXYNOS_MSCTRL_FIELD_MASK (1 << 31)
+#define EXYNOS_MSCTRL_FIELD_WEAVE (1 << 31)
+#define EXYNOS_MSCTRL_FIELD_NORMAL (0 << 31)
+#define EXYNOS_MSCTRL_BURST_CNT (24)
+#define EXYNOS_MSCTRL_BURST_CNT_MASK (0xf << 24)
+#define EXYNOS_MSCTRL_ORDER2P_LSB_CBCR (0 << 16)
+#define EXYNOS_MSCTRL_ORDER2P_LSB_CRCB (1 << 16)
+#define EXYNOS_MSCTRL_ORDER2P_MSB_CRCB (2 << 16)
+#define EXYNOS_MSCTRL_ORDER2P_MSB_CBCR (3 << 16)
+#define EXYNOS_MSCTRL_ORDER2P_SHIFT (16)
+#define EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK (0x3 << 16)
+#define EXYNOS_MSCTRL_C_INT_IN_3PLANE (0 << 15)
+#define EXYNOS_MSCTRL_C_INT_IN_2PLANE (1 << 15)
+#define EXYNOS_MSCTRL_FLIP_SHIFT (13)
+#define EXYNOS_MSCTRL_FLIP_NORMAL (0 << 13)
+#define EXYNOS_MSCTRL_FLIP_X_MIRROR (1 << 13)
+#define EXYNOS_MSCTRL_FLIP_Y_MIRROR (2 << 13)
+#define EXYNOS_MSCTRL_FLIP_180 (3 << 13)
+#define EXYNOS_MSCTRL_FLIP_MASK (3 << 13)
+#define EXYNOS_MSCTRL_ORDER422_CRYCBY (0 << 4)
+#define EXYNOS_MSCTRL_ORDER422_YCRYCB (1 << 4)
+#define EXYNOS_MSCTRL_ORDER422_CBYCRY (2 << 4)
+#define EXYNOS_MSCTRL_ORDER422_YCBYCR (3 << 4)
+#define EXYNOS_MSCTRL_INPUT_EXTCAM (0 << 3)
+#define EXYNOS_MSCTRL_INPUT_MEMORY (1 << 3)
+#define EXYNOS_MSCTRL_INPUT_MASK (1 << 3)
+#define EXYNOS_MSCTRL_INFORMAT_YCBCR420 (0 << 1)
+#define EXYNOS_MSCTRL_INFORMAT_YCBCR422 (1 << 1)
+#define EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE (2 << 1)
+#define EXYNOS_MSCTRL_INFORMAT_RGB (3 << 1)
+#define EXYNOS_MSCTRL_ENVID (1 << 0)
+
+/* DMA parameter register */
+#define EXYNOS_CIDMAPARAM_R_MODE_LINEAR (0 << 29)
+#define EXYNOS_CIDMAPARAM_R_MODE_CONFTILE (1 << 29)
+#define EXYNOS_CIDMAPARAM_R_MODE_16X16 (2 << 29)
+#define EXYNOS_CIDMAPARAM_R_MODE_64X32 (3 << 29)
+#define EXYNOS_CIDMAPARAM_R_MODE_MASK (3 << 29)
+#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_64 (0 << 24)
+#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_128 (1 << 24)
+#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_256 (2 << 24)
+#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_512 (3 << 24)
+#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_1024 (4 << 24)
+#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_2048 (5 << 24)
+#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_4096 (6 << 24)
+#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_1 (0 << 20)
+#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_2 (1 << 20)
+#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_4 (2 << 20)
+#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_8 (3 << 20)
+#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_16 (4 << 20)
+#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_32 (5 << 20)
+#define EXYNOS_CIDMAPARAM_W_MODE_LINEAR (0 << 13)
+#define EXYNOS_CIDMAPARAM_W_MODE_CONFTILE (1 << 13)
+#define EXYNOS_CIDMAPARAM_W_MODE_16X16 (2 << 13)
+#define EXYNOS_CIDMAPARAM_W_MODE_64X32 (3 << 13)
+#define EXYNOS_CIDMAPARAM_W_MODE_MASK (3 << 13)
+#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_64 (0 << 8)
+#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_128 (1 << 8)
+#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_256 (2 << 8)
+#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_512 (3 << 8)
+#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_1024 (4 << 8)
+#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_2048 (5 << 8)
+#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_4096 (6 << 8)
+#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_1 (0 << 4)
+#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_2 (1 << 4)
+#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_4 (2 << 4)
+#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_8 (3 << 4)
+#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_16 (4 << 4)
+#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_32 (5 << 4)
+
+/* Gathering Extension register */
+#define EXYNOS_CIEXTEN_TARGETH_EXT_MASK (1 << 26)
+#define EXYNOS_CIEXTEN_TARGETV_EXT_MASK (1 << 24)
+#define EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK (0x3F << 10)
+#define EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK (0x3F)
+#define EXYNOS_CIEXTEN_YUV444_OUT (1 << 22)
+
+/* FIMC Clock Source Select register */
+#define EXYNOS_CLKSRC_HCLK (0 << 1)
+#define EXYNOS_CLKSRC_HCLK_MASK (1 << 1)
+#define EXYNOS_CLKSRC_SCLK (1 << 1)
+
+/* SYSREG for FIMC writeback */
+#define SYSREG_CAMERA_BLK (S3C_VA_SYS + 0x0218)
+#define SYSREG_ISP_BLK (S3C_VA_SYS + 0x020c)
+#define SYSREG_FIMD0WB_DEST_MASK (0x3 << 23)
+#define SYSREG_FIMD0WB_DEST_SHIFT 23
+
+#endif /* SAMSUNG_REGS_FIMC_H */
diff --git a/drivers/gpu/drm/exynos/regs-gsc.h b/drivers/gpu/drm/exynos/regs-gsc.h
new file mode 100644
index 0000000..8ec160b
--- /dev/null
+++ b/drivers/gpu/drm/exynos/regs-gsc.h
@@ -0,0 +1,295 @@
+/* linux/drivers/gpu/drm/exynos/regs-gsc.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Register definition file for Samsung G-Scaler driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef REGS_GSC_H_
+#define REGS_GSC_H_
+
+/* SYSCON. GSCBLK_CFG */
+#include <plat/map-base.h>
+#include <plat/cpu.h>
+#define SYSREG_DISP1BLK_CFG (S3C_VA_SYS + 0x0214)
+#define FIFORST_DISP1 (1 << 23)
+#define GSC_OUT_MIXER0 (1 << 7)
+#define GSC_OUT_MIXER0_GSC3 (3 << 5)
+#define SYSREG_GSCBLK_CFG0 (S3C_VA_SYS + 0x0220)
+#define GSC_OUT_DST_FIMD_SEL(x) (1 << (8 + 2 * (x)))
+#define GSC_OUT_DST_MXR_SEL(x) (2 << (8 + 2 * (x)))
+#define GSC_PXLASYNC_RST(x) (1 << (x))
+#define PXLASYNC_LO_MASK_CAMIF_TOP (1 << 20)
+#define SYSREG_GSCBLK_CFG1 (S3C_VA_SYS + 0x0224)
+#define GSC_BLK_DISP1WB_DEST(x) (x << 10)
+#define GSC_BLK_SW_RESET_WB_DEST(x) (1 << (18 + x))
+#define GSC_BLK_PXLASYNC_LO_MASK_WB(x) (0 << (14 + x))
+#define GSC_BLK_GSCL_WB_IN_SRC_SEL(x) (1 << (2 * x))
+#define SYSREG_GSCBLK_CFG2 (S3C_VA_SYS + 0x2000)
+#define PXLASYNC_LO_MASK_CAMIF_GSCL(x) (1 << (x))
+
+/* G-Scaler enable */
+#define GSC_ENABLE 0x00
+#define GSC_ENABLE_PP_UPDATE_TIME_MASK (1 << 9)
+#define GSC_ENABLE_PP_UPDATE_TIME_CURR (0 << 9)
+#define GSC_ENABLE_PP_UPDATE_TIME_EOPAS (1 << 9)
+#define GSC_ENABLE_CLK_GATE_MODE_MASK (1 << 8)
+#define GSC_ENABLE_CLK_GATE_MODE_FREE (1 << 8)
+#define GSC_ENABLE_IPC_MODE_MASK (1 << 7)
+#define GSC_ENABLE_NORM_MODE (0 << 7)
+#define GSC_ENABLE_IPC_MODE (1 << 7)
+#define GSC_ENABLE_PP_UPDATE_MODE_MASK (1 << 6)
+#define GSC_ENABLE_PP_UPDATE_FIRE_MODE (1 << 6)
+#define GSC_ENABLE_IN_PP_UPDATE (1 << 5)
+#define GSC_ENABLE_ON_CLEAR_MASK (1 << 4)
+#define GSC_ENABLE_ON_CLEAR_ONESHOT (1 << 4)
+#define GSC_ENABLE_QOS_ENABLE (1 << 3)
+#define GSC_ENABLE_OP_STATUS (1 << 2)
+#define GSC_ENABLE_SFR_UPDATE (1 << 1)
+#define GSC_ENABLE_ON (1 << 0)
+
+/* G-Scaler S/W reset */
+#define GSC_SW_RESET 0x04
+#define GSC_SW_RESET_SRESET (1 << 0)
+
+/* G-Scaler IRQ */
+#define GSC_IRQ 0x08
+#define GSC_IRQ_STATUS_OR_IRQ (1 << 17)
+#define GSC_IRQ_STATUS_OR_FRM_DONE (1 << 16)
+#define GSC_IRQ_OR_MASK (1 << 2)
+#define GSC_IRQ_FRMDONE_MASK (1 << 1)
+#define GSC_IRQ_ENABLE (1 << 0)
+
+/* G-Scaler input control */
+#define GSC_IN_CON 0x10
+#define GSC_IN_CHROM_STRIDE_SEL_MASK (1 << 20)
+#define GSC_IN_CHROM_STRIDE_SEPAR (1 << 20)
+#define GSC_IN_RB_SWAP_MASK (1 << 19)
+#define GSC_IN_RB_SWAP (1 << 19)
+#define GSC_IN_ROT_MASK (7 << 16)
+#define GSC_IN_ROT_270 (7 << 16)
+#define GSC_IN_ROT_90_YFLIP (6 << 16)
+#define GSC_IN_ROT_90_XFLIP (5 << 16)
+#define GSC_IN_ROT_90 (4 << 16)
+#define GSC_IN_ROT_180 (3 << 16)
+#define GSC_IN_ROT_YFLIP (2 << 16)
+#define GSC_IN_ROT_XFLIP (1 << 16)
+#define GSC_IN_RGB_TYPE_MASK (3 << 14)
+#define GSC_IN_RGB_HD_WIDE (3 << 14)
+#define GSC_IN_RGB_HD_NARROW (2 << 14)
+#define GSC_IN_RGB_SD_WIDE (1 << 14)
+#define GSC_IN_RGB_SD_NARROW (0 << 14)
+#define GSC_IN_YUV422_1P_ORDER_MASK (1 << 13)
+#define GSC_IN_YUV422_1P_ORDER_LSB_Y (0 << 13)
+#define GSC_IN_YUV422_1P_OEDER_LSB_C (1 << 13)
+#define GSC_IN_CHROMA_ORDER_MASK (1 << 12)
+#define GSC_IN_CHROMA_ORDER_CBCR (0 << 12)
+#define GSC_IN_CHROMA_ORDER_CRCB (1 << 12)
+#define GSC_IN_FORMAT_MASK (7 << 8)
+#define GSC_IN_XRGB8888 (0 << 8)
+#define GSC_IN_RGB565 (1 << 8)
+#define GSC_IN_YUV420_2P (2 << 8)
+#define GSC_IN_YUV420_3P (3 << 8)
+#define GSC_IN_YUV422_1P (4 << 8)
+#define GSC_IN_YUV422_2P (5 << 8)
+#define GSC_IN_YUV422_3P (6 << 8)
+#define GSC_IN_TILE_TYPE_MASK (1 << 4)
+#define GSC_IN_TILE_C_16x8 (0 << 4)
+#define GSC_IN_TILE_C_16x16 (1 << 4)
+#define GSC_IN_TILE_MODE (1 << 3)
+#define GSC_IN_LOCAL_SEL_MASK (3 << 1)
+#define GSC_IN_LOCAL_CAM3 (3 << 1)
+#define GSC_IN_LOCAL_FIMD_WB (2 << 1)
+#define GSC_IN_LOCAL_CAM1 (1 << 1)
+#define GSC_IN_LOCAL_CAM0 (0 << 1)
+#define GSC_IN_PATH_MASK (1 << 0)
+#define GSC_IN_PATH_LOCAL (1 << 0)
+#define GSC_IN_PATH_MEMORY (0 << 0)
+
+/* G-Scaler source image size */
+#define GSC_SRCIMG_SIZE 0x14
+#define GSC_SRCIMG_HEIGHT_MASK (0x1fff << 16)
+#define GSC_SRCIMG_HEIGHT(x) ((x) << 16)
+#define GSC_SRCIMG_WIDTH_MASK (0x3fff << 0)
+#define GSC_SRCIMG_WIDTH(x) ((x) << 0)
+
+/* G-Scaler source image offset */
+#define GSC_SRCIMG_OFFSET 0x18
+#define GSC_SRCIMG_OFFSET_Y_MASK (0x1fff << 16)
+#define GSC_SRCIMG_OFFSET_Y(x) ((x) << 16)
+#define GSC_SRCIMG_OFFSET_X_MASK (0x1fff << 0)
+#define GSC_SRCIMG_OFFSET_X(x) ((x) << 0)
+
+/* G-Scaler cropped source image size */
+#define GSC_CROPPED_SIZE 0x1C
+#define GSC_CROPPED_HEIGHT_MASK (0x1fff << 16)
+#define GSC_CROPPED_HEIGHT(x) ((x) << 16)
+#define GSC_CROPPED_WIDTH_MASK (0x1fff << 0)
+#define GSC_CROPPED_WIDTH(x) ((x) << 0)
+
+/* G-Scaler output control */
+#define GSC_OUT_CON 0x20
+#define GSC_OUT_GLOBAL_ALPHA_MASK (0xff << 24)
+#define GSC_OUT_GLOBAL_ALPHA(x) ((x) << 24)
+#define GSC_OUT_CHROM_STRIDE_SEL_MASK (1 << 13)
+#define GSC_OUT_CHROM_STRIDE_SEPAR (1 << 13)
+#define GSC_OUT_RB_SWAP_MASK (1 << 12)
+#define GSC_OUT_RB_SWAP (1 << 12)
+#define GSC_OUT_RGB_TYPE_MASK (3 << 10)
+#define GSC_OUT_RGB_HD_NARROW (3 << 10)
+#define GSC_OUT_RGB_HD_WIDE (2 << 10)
+#define GSC_OUT_RGB_SD_NARROW (1 << 10)
+#define GSC_OUT_RGB_SD_WIDE (0 << 10)
+#define GSC_OUT_YUV422_1P_ORDER_MASK (1 << 9)
+#define GSC_OUT_YUV422_1P_ORDER_LSB_Y (0 << 9)
+#define GSC_OUT_YUV422_1P_OEDER_LSB_C (1 << 9)
+#define GSC_OUT_CHROMA_ORDER_MASK (1 << 8)
+#define GSC_OUT_CHROMA_ORDER_CBCR (0 << 8)
+#define GSC_OUT_CHROMA_ORDER_CRCB (1 << 8)
+#define GSC_OUT_FORMAT_MASK (7 << 4)
+#define GSC_OUT_XRGB8888 (0 << 4)
+#define GSC_OUT_RGB565 (1 << 4)
+#define GSC_OUT_YUV420_2P (2 << 4)
+#define GSC_OUT_YUV420_3P (3 << 4)
+#define GSC_OUT_YUV422_1P (4 << 4)
+#define GSC_OUT_YUV422_2P (5 << 4)
+#define GSC_OUT_YUV444 (7 << 4)
+#define GSC_OUT_TILE_TYPE_MASK (1 << 2)
+#define GSC_OUT_TILE_C_16x8 (0 << 2)
+#define GSC_OUT_TILE_C_16x16 (1 << 2)
+#define GSC_OUT_TILE_MODE (1 << 1)
+#define GSC_OUT_PATH_MASK (1 << 0)
+#define GSC_OUT_PATH_LOCAL (1 << 0)
+#define GSC_OUT_PATH_MEMORY (0 << 0)
+
+/* G-Scaler scaled destination image size */
+#define GSC_SCALED_SIZE 0x24
+#define GSC_SCALED_HEIGHT_MASK (0x1fff << 16)
+#define GSC_SCALED_HEIGHT(x) ((x) << 16)
+#define GSC_SCALED_WIDTH_MASK (0x1fff << 0)
+#define GSC_SCALED_WIDTH(x) ((x) << 0)
+
+/* G-Scaler pre scale ratio */
+#define GSC_PRE_SCALE_RATIO 0x28
+#define GSC_PRESC_SHFACTOR_MASK (7 << 28)
+#define GSC_PRESC_SHFACTOR(x) ((x) << 28)
+#define GSC_PRESC_V_RATIO_MASK (7 << 16)
+#define GSC_PRESC_V_RATIO(x) ((x) << 16)
+#define GSC_PRESC_H_RATIO_MASK (7 << 0)
+#define GSC_PRESC_H_RATIO(x) ((x) << 0)
+
+/* G-Scaler main scale horizontal ratio */
+#define GSC_MAIN_H_RATIO 0x2C
+#define GSC_MAIN_H_RATIO_MASK (0xfffff << 0)
+#define GSC_MAIN_H_RATIO_VALUE(x) ((x) << 0)
+
+/* G-Scaler main scale vertical ratio */
+#define GSC_MAIN_V_RATIO 0x30
+#define GSC_MAIN_V_RATIO_MASK (0xfffff << 0)
+#define GSC_MAIN_V_RATIO_VALUE(x) ((x) << 0)
+
+/* G-Scaler input chrominance stride */
+#define GSC_IN_CHROM_STRIDE 0x3C
+#define GSC_IN_CHROM_STRIDE_MASK (0x3fff << 0)
+#define GSC_IN_CHROM_STRIDE_VALUE(x) ((x) << 0)
+
+/* G-Scaler destination image size */
+#define GSC_DSTIMG_SIZE 0x40
+#define GSC_DSTIMG_HEIGHT_MASK (0x1fff << 16)
+#define GSC_DSTIMG_HEIGHT(x) ((x) << 16)
+#define GSC_DSTIMG_WIDTH_MASK (0x1fff << 0)
+#define GSC_DSTIMG_WIDTH(x) ((x) << 0)
+
+/* G-Scaler destination image offset */
+#define GSC_DSTIMG_OFFSET 0x44
+#define GSC_DSTIMG_OFFSET_Y_MASK (0x1fff << 16)
+#define GSC_DSTIMG_OFFSET_Y(x) ((x) << 16)
+#define GSC_DSTIMG_OFFSET_X_MASK (0x1fff << 0)
+#define GSC_DSTIMG_OFFSET_X(x) ((x) << 0)
+
+/* G-Scaler output chrominance stride */
+#define GSC_OUT_CHROM_STRIDE 0x48
+#define GSC_OUT_CHROM_STRIDE_MASK (0x3fff << 0)
+#define GSC_OUT_CHROM_STRIDE_VALUE(x) ((x) << 0)
+
+/* G-Scaler input y address mask */
+#define GSC_IN_BASE_ADDR_Y_MASK 0x4C
+/* G-Scaler input y base address */
+#define GSC_IN_BASE_ADDR_Y(n) (0x50 + (n) * 0x4)
+/* G-Scaler input y base current address */
+#define GSC_IN_BASE_ADDR_Y_CUR(n) (0x60 + (n) * 0x4)
+
+/* G-Scaler input cb address mask */
+#define GSC_IN_BASE_ADDR_CB_MASK 0x7C
+/* G-Scaler input cb base address */
+#define GSC_IN_BASE_ADDR_CB(n) (0x80 + (n) * 0x4)
+/* G-Scaler input cb base current address */
+#define GSC_IN_BASE_ADDR_CB_CUR(n) (0x90 + (n) * 0x4)
+
+/* G-Scaler input cr address mask */
+#define GSC_IN_BASE_ADDR_CR_MASK 0xAC
+/* G-Scaler input cr base address */
+#define GSC_IN_BASE_ADDR_CR(n) (0xB0 + (n) * 0x4)
+/* G-Scaler input cr base current address */
+#define GSC_IN_BASE_ADDR_CR_CUR(n) (0xC0 + (n) * 0x4)
+
+/* G-Scaler input address mask */
+#define GSC_IN_CURR_ADDR_INDEX (0xf << 24)
+#define GSC_IN_CURR_GET_INDEX(x) ((x) >> 24)
+#define GSC_IN_BASE_ADDR_PINGPONG(x) ((x) << 16)
+#define GSC_IN_BASE_ADDR_MASK (0xff << 0)
+
+/* G-Scaler output y address mask */
+#define GSC_OUT_BASE_ADDR_Y_MASK 0x10C
+/* G-Scaler output y base address */
+#define GSC_OUT_BASE_ADDR_Y(n) (0x110 + (n) * 0x4)
+
+/* G-Scaler output cb address mask */
+#define GSC_OUT_BASE_ADDR_CB_MASK 0x15C
+/* G-Scaler output cb base address */
+#define GSC_OUT_BASE_ADDR_CB(n) (0x160 + (n) * 0x4)
+
+/* G-Scaler output cr address mask */
+#define GSC_OUT_BASE_ADDR_CR_MASK 0x1AC
+/* G-Scaler output cr base address */
+#define GSC_OUT_BASE_ADDR_CR(n) (0x1B0 + (n) * 0x4)
+
+/* G-Scaler output address mask */
+#define GSC_OUT_CURR_ADDR_INDEX (0xf << 24)
+#define GSC_OUT_CURR_GET_INDEX(x) ((x) >> 24)
+#define GSC_OUT_BASE_ADDR_PINGPONG(x) ((x) << 16)
+#define GSC_OUT_BASE_ADDR_MASK (0xffff << 0)
+
+/* G-Scaler horizontal scaling filter */
+#define GSC_HCOEF(n, s, x) (0x300 + (n) * 0x4 + (s) * 0x30 + (x) * 0x300)
+
+/* G-Scaler vertical scaling filter */
+#define GSC_VCOEF(n, s, x) (0x200 + (n) * 0x4 + (s) * 0x30 + (x) * 0x300)
+
+/* G-Scaler BUS control */
+#define GSC_BUSCON 0xA78
+#define GSC_BUSCON_INT_TIME_MASK (1 << 8)
+#define GSC_BUSCON_INT_DATA_TRANS (0 << 8)
+#define GSC_BUSCON_INT_AXI_RESPONSE (1 << 8)
+#define GSC_BUSCON_AWCACHE(x) ((x) << 4)
+#define GSC_BUSCON_ARCACHE(x) ((x) << 0)
+
+/* G-Scaler V position */
+#define GSC_VPOSITION 0xA7C
+#define GSC_VPOS_F(x) ((x) << 0)
+
+
+/* G-Scaler clock initial count */
+#define GSC_CLK_INIT_COUNT 0xC00
+#define GSC_CLK_GATE_MODE_INIT_CNT(x) ((x) << 0)
+
+/* G-Scaler clock snoop count */
+#define GSC_CLK_SNOOP_COUNT 0xC04
+#define GSC_CLK_GATE_MODE_SNOOP_CNT(x) ((x) << 0)
+
+#endif /* REGS_GSC_H_ */
diff --git a/drivers/gpu/drm/exynos_tmp/Kconfig b/drivers/gpu/drm/exynos_tmp/Kconfig
deleted file mode 100644
index 4466490..0000000
--- a/drivers/gpu/drm/exynos_tmp/Kconfig
+++ /dev/null
@@ -1,46 +0,0 @@
-config DRM_EXYNOS
- tristate "DRM Support for Samsung SoC EXYNOS Series"
- depends on DRM && PLAT_SAMSUNG
- select DRM_KMS_HELPER
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
-
-config DRM_EXYNOS_MEMSIZE
- int "Memory size in kbytes for DRM"
- depends on DRM_EXYNOS
- default "32768"
-
-config DRM_EXYNOS_DMABUF
- bool "GEM DMABUF Support"
- depends on DRM_EXYNOS
-
-config DRM_EXYNOS_FIMD
- bool "Samsung DRM FIMD"
- depends on DRM_EXYNOS
-
-config DRM_EXYNOS_FIMD_WB
- bool "Samsung DRM FIMD WB"
- depends on DRM_EXYNOS_FIMD
- help
- This option enables writeback operations in FIMD for DRM.
- It can support fimd streams data to fimc destinations ram.
- writeback operations support final blended stream.
- when enable this options.
-
-config DRM_EXYNOS_HDMI
- bool "Samsung DRM HDMI"
- depends on DRM_EXYNOS
-
-config DRM_EXYNOS_VIDI
- bool "Samsung DRM Virtual Display"
- depends on DRM_EXYNOS
-
-config DRM_EXYNOS_G2D
- bool "Samsung DRM G2D"
- depends on DRM_EXYNOS
-
-config DRM_EXYNOS_ROTATOR
- bool "Samsung DRM Rotator"
- depends on DRM_EXYNOS
diff --git a/drivers/gpu/drm/exynos_tmp/Makefile b/drivers/gpu/drm/exynos_tmp/Makefile
deleted file mode 100644
index f8a88f3..0000000
--- a/drivers/gpu/drm/exynos_tmp/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Makefile for the drm device driver. This driver provides support for the
-# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-
-ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos \
- -Idrivers/media/video/samsung/ump/include
-exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
- exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \
- exynos_drm_buf.o exynos_drm_ump.o exynos_drm_gem.o \
- exynos_drm_core.o exynos_drm_plane.o exynos_drm_iommu.o
-
-exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o exynos_ddc.o \
- exynos_hdmiphy.o exynos_drm_hdmi.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o
-
-obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_ddc.c b/drivers/gpu/drm/exynos_tmp/exynos_ddc.c
deleted file mode 100644
index 7e1051d..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_ddc.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- * Inki Dae <inki.dae@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include "drmP.h"
-
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-
-
-#include "exynos_drm_drv.h"
-#include "exynos_hdmi.h"
-
-static int s5p_ddc_probe(struct i2c_client *client,
- const struct i2c_device_id *dev_id)
-{
- hdmi_attach_ddc_client(client);
-
- dev_info(&client->adapter->dev, "attached s5p_ddc "
- "into i2c adapter successfully\n");
-
- return 0;
-}
-
-static int s5p_ddc_remove(struct i2c_client *client)
-{
- dev_info(&client->adapter->dev, "detached s5p_ddc "
- "from i2c adapter successfully\n");
-
- return 0;
-}
-
-static struct i2c_device_id ddc_idtable[] = {
- {"s5p_ddc", 0},
- { },
-};
-
-struct i2c_driver ddc_driver = {
- .driver = {
- .name = "s5p_ddc",
- .owner = THIS_MODULE,
- },
- .id_table = ddc_idtable,
- .probe = s5p_ddc_probe,
- .remove = __devexit_p(s5p_ddc_remove),
- .command = NULL,
-};
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_buf.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_buf.c
deleted file mode 100644
index f7bb7be..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_buf.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/* exynos_drm_buf.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Author: Inki Dae <inki.dae@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "exynos_drm.h"
-
-#include <linux/cma.h>
-#include "exynos_drm_drv.h"
-#include "exynos_drm_gem.h"
-#include "exynos_drm_buf.h"
-
-static int lowlevel_buffer_allocate(struct drm_device *dev,
- unsigned int flags, struct exynos_drm_gem_buf *buf)
-{
- dma_addr_t start_addr;
- unsigned int npages, i = 0;
- struct scatterlist *sgl;
- int ret = 0;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (IS_NONCONTIG_BUFFER(flags)) {
- DRM_DEBUG_KMS("not support allocation type.\n");
- return -EINVAL;
- }
-
- if (buf->dma_addr) {
- DRM_DEBUG_KMS("already allocated.\n");
- return 0;
- }
-
- if (buf->size >= SZ_1M) {
- npages = buf->size >> SECTION_SHIFT;
- buf->page_size = SECTION_SIZE;
- } else if (buf->size >= SZ_64K) {
- npages = buf->size >> 16;
- buf->page_size = SZ_64K;
- } else {
- npages = buf->size >> PAGE_SHIFT;
- buf->page_size = PAGE_SIZE;
- }
-
- buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
- if (!buf->sgt) {
- DRM_ERROR("failed to allocate sg table.\n");
- return -ENOMEM;
- }
-
- ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL);
- if (ret < 0) {
- DRM_ERROR("failed to initialize sg table.\n");
- kfree(buf->sgt);
- buf->sgt = NULL;
- return -ENOMEM;
- }
-
-#ifdef CONFIG_CMA
- buf->dma_addr = cma_alloc(dev->dev, "drm", buf->size,
- buf->page_size);
- if (IS_ERR((void *)buf->dma_addr)) {
- DRM_DEBUG_KMS("cma_alloc of size %ld failed\n",
- buf->size);
- ret = -ENOMEM;
- goto err1;
- }
-
- buf->kvaddr = phys_to_virt(buf->dma_addr);
-#else
- /* align it as page size(page or section) TODO */
-
- buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size,
- &buf->dma_addr, GFP_KERNEL);
- if (!buf->kvaddr) {
- DRM_ERROR("failed to allocate buffer.\n");
- ret = -ENOMEM;
- goto err1;
- }
-#endif
- buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
- if (!buf->pages) {
- DRM_ERROR("failed to allocate pages.\n");
- ret = -ENOMEM;
- goto err2;
- }
-
- sgl = buf->sgt->sgl;
- start_addr = buf->dma_addr;
-
- while (i < npages) {
- buf->pages[i] = phys_to_page(start_addr);
- sg_set_page(sgl, buf->pages[i], buf->page_size, 0);
- sg_dma_address(sgl) = start_addr;
- start_addr += buf->page_size;
- sgl = sg_next(sgl);
- i++;
- }
-
- DRM_INFO("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
- (unsigned long)buf->kvaddr,
- (unsigned long)buf->dma_addr,
- buf->size);
-
- return ret;
-err2:
-#ifdef CONFIG_CMA
- cma_free(buf->dma_addr);
-#else
- dma_free_writecombine(dev->dev, buf->size, buf->kvaddr,
- (dma_addr_t)buf->dma_addr);
-#endif
- buf->dma_addr = (dma_addr_t)NULL;
-err1:
- sg_free_table(buf->sgt);
- kfree(buf->sgt);
- buf->sgt = NULL;
-
- return ret;
-}
-
-static void lowlevel_buffer_deallocate(struct drm_device *dev,
- unsigned int flags, struct exynos_drm_gem_buf *buf)
-{
- DRM_DEBUG_KMS("%s.\n", __FILE__);
-
- /*
- * now buffer is being shared and it would be released
- * by original owner so ignor free action.
- */
- if (buf->shared || atomic_read(&buf->shared_refcount))
- return;
-
- /*
- * release only physically continuous memory and
- * non-continuous memory would be released by exynos
- * gem framework.
- */
- if (IS_NONCONTIG_BUFFER(flags)) {
- DRM_DEBUG_KMS("not support allocation type.\n");
- return;
- }
-
- if (!buf->dma_addr) {
- DRM_DEBUG_KMS("dma_addr is invalid.\n");
- return;
- }
-
- sg_free_table(buf->sgt);
-
- kfree(buf->sgt);
- buf->sgt = NULL;
-
- kfree(buf->pages);
- buf->pages = NULL;
-#ifdef CONFIG_CMA
- cma_free(buf->dma_addr);
-#else
- dma_free_writecombine(dev->dev, buf->size, buf->kvaddr,
- (dma_addr_t)buf->dma_addr);
-#endif
- buf->dma_addr = (dma_addr_t)NULL;
-}
-
-struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev,
- unsigned int size)
-{
- struct exynos_drm_gem_buf *buffer;
-
- DRM_DEBUG_KMS("%s.\n", __FILE__);
- DRM_DEBUG_KMS("desired size = 0x%x\n", size);
-
- buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
- if (!buffer) {
- DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
- return NULL;
- }
-
- buffer->size = size;
- return buffer;
-}
-
-void exynos_drm_fini_buf(struct drm_device *dev,
- struct exynos_drm_gem_buf *buffer)
-{
- DRM_DEBUG_KMS("%s.\n", __FILE__);
-
- if (!buffer) {
- DRM_DEBUG_KMS("buffer is null.\n");
- return;
- }
-
- kfree(buffer);
- buffer = NULL;
-}
-
-int exynos_drm_alloc_buf(struct drm_device *dev,
- struct exynos_drm_gem_buf *buf, unsigned int flags)
-{
-
- /*
- * allocate memory region and set the memory information
- * to vaddr and dma_addr of a buffer object.
- */
- if (lowlevel_buffer_allocate(dev, flags, buf) < 0)
- return -ENOMEM;
-
- return 0;
-}
-
-void exynos_drm_free_buf(struct drm_device *dev,
- unsigned int flags, struct exynos_drm_gem_buf *buffer)
-{
-
- lowlevel_buffer_deallocate(dev, flags, buffer);
-}
-
-MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC DRM Buffer Management Module");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_buf.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_buf.h
deleted file mode 100644
index 3388e4e..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_buf.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* exynos_drm_buf.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Author: Inki Dae <inki.dae@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_BUF_H_
-#define _EXYNOS_DRM_BUF_H_
-
-/* create and initialize buffer object. */
-struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev,
- unsigned int size);
-
-/* destroy buffer object. */
-void exynos_drm_fini_buf(struct drm_device *dev,
- struct exynos_drm_gem_buf *buffer);
-
-/* allocate physical memory region and setup sgt and pages. */
-int exynos_drm_alloc_buf(struct drm_device *dev,
- struct exynos_drm_gem_buf *buf,
- unsigned int flags);
-
-/* release physical memory region, sgt and pages. */
-void exynos_drm_free_buf(struct drm_device *dev,
- unsigned int flags,
- struct exynos_drm_gem_buf *buffer);
-
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_connector.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_connector.c
deleted file mode 100644
index 0efb6df..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_connector.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm_crtc_helper.h"
-
-#include <drm/exynos_drm.h>
-#include "exynos_drm_drv.h"
-#include "exynos_drm_encoder.h"
-
-#define MAX_EDID 256
-#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
- drm_connector)
-
-struct exynos_drm_connector {
- struct drm_connector drm_connector;
- uint32_t encoder_id;
- struct exynos_drm_manager *manager;
-};
-
-/* convert exynos_video_timings to drm_display_mode */
-static inline void
-convert_to_display_mode(struct drm_display_mode *mode,
- struct exynos_drm_panel_info *panel)
-{
- struct fb_videomode *timing = &panel->timing;
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- mode->clock = timing->pixclock / 1000;
- mode->vrefresh = timing->refresh;
-
- mode->hdisplay = timing->xres;
- mode->hsync_start = mode->hdisplay + timing->right_margin;
- mode->hsync_end = mode->hsync_start + timing->hsync_len;
- mode->htotal = mode->hsync_end + timing->left_margin;
-
- mode->vdisplay = timing->yres;
- mode->vsync_start = mode->vdisplay + timing->lower_margin;
- mode->vsync_end = mode->vsync_start + timing->vsync_len;
- mode->vtotal = mode->vsync_end + timing->upper_margin;
- mode->width_mm = panel->width_mm;
- mode->height_mm = panel->height_mm;
-
- if (timing->vmode & FB_VMODE_INTERLACED)
- mode->flags |= DRM_MODE_FLAG_INTERLACE;
-
- if (timing->vmode & FB_VMODE_DOUBLE)
- mode->flags |= DRM_MODE_FLAG_DBLSCAN;
-}
-
-/* convert drm_display_mode to exynos_video_timings */
-static inline void
-convert_to_video_timing(struct fb_videomode *timing,
- struct drm_display_mode *mode)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- memset(timing, 0, sizeof(*timing));
-
- timing->pixclock = mode->clock * 1000;
- timing->refresh = drm_mode_vrefresh(mode);
-
- timing->xres = mode->hdisplay;
- timing->right_margin = mode->hsync_start - mode->hdisplay;
- timing->hsync_len = mode->hsync_end - mode->hsync_start;
- timing->left_margin = mode->htotal - mode->hsync_end;
-
- timing->yres = mode->vdisplay;
- timing->lower_margin = mode->vsync_start - mode->vdisplay;
- timing->vsync_len = mode->vsync_end - mode->vsync_start;
- timing->upper_margin = mode->vtotal - mode->vsync_end;
-
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- timing->vmode = FB_VMODE_INTERLACED;
- else
- timing->vmode = FB_VMODE_NONINTERLACED;
-
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- timing->vmode |= FB_VMODE_DOUBLE;
-}
-
-static int exynos_drm_connector_get_modes(struct drm_connector *connector)
-{
- struct exynos_drm_connector *exynos_connector =
- to_exynos_connector(connector);
- struct exynos_drm_manager *manager = exynos_connector->manager;
- struct exynos_drm_display_ops *display_ops = manager->display_ops;
- unsigned int count;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!display_ops) {
- DRM_DEBUG_KMS("display_ops is null.\n");
- return 0;
- }
-
- /*
- * if get_edid() exists then get_edid() callback of hdmi side
- * is called to get edid data through i2c interface else
- * get timing from the FIMD driver(display controller).
- *
- * P.S. in case of lcd panel, count is always 1 if success
- * because lcd panel has only one mode.
- */
- if (display_ops->get_edid) {
- int ret;
- void *edid;
-
- edid = kzalloc(MAX_EDID, GFP_KERNEL);
- if (!edid) {
- DRM_ERROR("failed to allocate edid\n");
- return 0;
- }
-
- ret = display_ops->get_edid(manager->dev, connector,
- edid, MAX_EDID);
- if (ret < 0) {
- DRM_ERROR("failed to get edid data.\n");
- kfree(edid);
- edid = NULL;
- return 0;
- }
-
- drm_mode_connector_update_edid_property(connector, edid);
- count = drm_add_edid_modes(connector, edid);
-
- kfree(connector->display_info.raw_edid);
- connector->display_info.raw_edid = edid;
- } else {
- struct drm_display_mode *mode = drm_mode_create(connector->dev);
- struct exynos_drm_panel_info *panel;
-
- if (display_ops->get_panel)
- panel = display_ops->get_panel(manager->dev);
- else {
- drm_mode_destroy(connector->dev, mode);
- return 0;
- }
-
- convert_to_display_mode(mode, panel);
- connector->display_info.width_mm = mode->width_mm;
- connector->display_info.height_mm = mode->height_mm;
-
- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
- drm_mode_set_name(mode);
- drm_mode_probed_add(connector, mode);
-
- count = 1;
- }
-
- return count;
-}
-
-static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct exynos_drm_connector *exynos_connector =
- to_exynos_connector(connector);
- struct exynos_drm_manager *manager = exynos_connector->manager;
- struct exynos_drm_display_ops *display_ops = manager->display_ops;
- struct fb_videomode timing;
- int ret = MODE_BAD;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- convert_to_video_timing(&timing, mode);
-
- if (display_ops && display_ops->check_timing)
- if (!display_ops->check_timing(manager->dev, (void *)&timing))
- ret = MODE_OK;
-
- return ret;
-}
-
-struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct exynos_drm_connector *exynos_connector =
- to_exynos_connector(connector);
- struct drm_mode_object *obj;
- struct drm_encoder *encoder;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- obj = drm_mode_object_find(dev, exynos_connector->encoder_id,
- DRM_MODE_OBJECT_ENCODER);
- if (!obj) {
- DRM_DEBUG_KMS("Unknown ENCODER ID %d\n",
- exynos_connector->encoder_id);
- return NULL;
- }
-
- encoder = obj_to_encoder(obj);
-
- return encoder;
-}
-
-static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
- .get_modes = exynos_drm_connector_get_modes,
- .mode_valid = exynos_drm_connector_mode_valid,
- .best_encoder = exynos_drm_best_encoder,
-};
-
-static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
- unsigned int max_width, unsigned int max_height)
-{
- struct exynos_drm_connector *exynos_connector =
- to_exynos_connector(connector);
- struct exynos_drm_manager *manager = exynos_connector->manager;
- struct exynos_drm_manager_ops *ops = manager->ops;
- unsigned int width, height;
-
- width = max_width;
- height = max_height;
-
- /*
- * if specific driver want to find desired_mode using maxmum
- * resolution then get max width and height from that driver.
- */
- if (ops && ops->get_max_resol)
- ops->get_max_resol(manager->dev, &width, &height);
-
- return drm_helper_probe_single_connector_modes(connector, width,
- height);
-}
-
-/* get detection status of display device. */
-static enum drm_connector_status
-exynos_drm_connector_detect(struct drm_connector *connector, bool force)
-{
- struct exynos_drm_connector *exynos_connector =
- to_exynos_connector(connector);
- struct exynos_drm_manager *manager = exynos_connector->manager;
- struct exynos_drm_display_ops *display_ops =
- manager->display_ops;
- enum drm_connector_status status = connector_status_disconnected;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (display_ops && display_ops->is_connected) {
- if (display_ops->is_connected(manager->dev))
- status = connector_status_connected;
- else
- status = connector_status_disconnected;
- }
-
- return status;
-}
-
-static void exynos_drm_connector_destroy(struct drm_connector *connector)
-{
- struct exynos_drm_connector *exynos_connector =
- to_exynos_connector(connector);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
- kfree(exynos_connector);
-}
-
-static struct drm_connector_funcs exynos_connector_funcs = {
- .dpms = drm_helper_connector_dpms,
- .fill_modes = exynos_drm_connector_fill_modes,
- .detect = exynos_drm_connector_detect,
- .destroy = exynos_drm_connector_destroy,
-};
-
-struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
- struct drm_encoder *encoder)
-{
- struct exynos_drm_connector *exynos_connector;
- struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
- struct drm_connector *connector;
- int type;
- int err;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
- if (!exynos_connector) {
- DRM_ERROR("failed to allocate connector\n");
- return NULL;
- }
-
- connector = &exynos_connector->drm_connector;
-
- switch (manager->display_ops->type) {
- case EXYNOS_DISPLAY_TYPE_HDMI:
- type = DRM_MODE_CONNECTOR_HDMIA;
- connector->interlace_allowed = true;
- connector->polled = DRM_CONNECTOR_POLL_HPD;
- break;
- case EXYNOS_DISPLAY_TYPE_LCD:
- type = DRM_MODE_CONNECTOR_LVDS;
- break;
- case EXYNOS_DISPLAY_TYPE_VIDI:
- type = DRM_MODE_CONNECTOR_VIRTUAL;
- connector->polled = DRM_CONNECTOR_POLL_HPD;
- break;
- default:
- type = DRM_MODE_CONNECTOR_Unknown;
- break;
- }
-
- drm_connector_init(dev, connector, &exynos_connector_funcs, type);
- drm_connector_helper_add(connector, &exynos_connector_helper_funcs);
-
- err = drm_sysfs_connector_add(connector);
- if (err)
- goto err_connector;
-
- exynos_connector->encoder_id = encoder->base.id;
- exynos_connector->manager = manager;
- connector->encoder = encoder;
-
- err = drm_mode_connector_attach_encoder(connector, encoder);
- if (err) {
- DRM_ERROR("failed to attach a connector to a encoder\n");
- goto err_sysfs;
- }
-
- DRM_DEBUG_KMS("connector has been created\n");
-
- return connector;
-
-err_sysfs:
- drm_sysfs_connector_remove(connector);
-err_connector:
- drm_connector_cleanup(connector);
- kfree(exynos_connector);
- return NULL;
-}
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_core.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_core.c
deleted file mode 100644
index eaf630d..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_core.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/* exynos_drm_core.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Author:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "exynos_drm_drv.h"
-#include "exynos_drm_encoder.h"
-#include "exynos_drm_connector.h"
-#include "exynos_drm_fbdev.h"
-
-static LIST_HEAD(exynos_drm_subdrv_list);
-static struct drm_device *drm_dev;
-
-static int exynos_drm_subdrv_probe(struct drm_device *dev,
- struct exynos_drm_subdrv *subdrv)
-{
- struct drm_encoder *encoder;
- struct drm_connector *connector;
-
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (subdrv->probe) {
- int ret;
-
- /*
- * this probe callback would be called by sub driver
- * after setting of all resources to this sub driver,
- * such as clock, irq and register map are done or by load()
- * of exynos drm driver.
- *
- * P.S. note that this driver is considered for modularization.
- */
- ret = subdrv->probe(dev, subdrv->dev);
- if (ret)
- return ret;
- }
-
- if (!subdrv->manager)
- return 0;
-
- subdrv->manager->dev = subdrv->dev;
-
- /* create and initialize a encoder for this sub driver. */
- encoder = exynos_drm_encoder_create(dev, subdrv->manager,
- (1 << MAX_CRTC) - 1);
- if (!encoder) {
- DRM_ERROR("failed to create encoder\n");
- return -EFAULT;
- }
-
- /*
- * create and initialize a connector for this sub driver and
- * attach the encoder created above to the connector.
- */
- connector = exynos_drm_connector_create(dev, encoder);
- if (!connector) {
- DRM_ERROR("failed to create connector\n");
- encoder->funcs->destroy(encoder);
- return -EFAULT;
- }
-
- subdrv->encoder = encoder;
- subdrv->connector = connector;
-
- return 0;
-}
-
-static void exynos_drm_subdrv_remove(struct drm_device *dev,
- struct exynos_drm_subdrv *subdrv)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (subdrv->remove)
- subdrv->remove(dev);
-
- if (subdrv->encoder) {
- struct drm_encoder *encoder = subdrv->encoder;
- encoder->funcs->destroy(encoder);
- subdrv->encoder = NULL;
- }
-
- if (subdrv->connector) {
- struct drm_connector *connector = subdrv->connector;
- connector->funcs->destroy(connector);
- subdrv->connector = NULL;
- }
-}
-
-int exynos_drm_device_register(struct drm_device *dev)
-{
- struct exynos_drm_subdrv *subdrv, *n;
- int err;
-
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (!dev)
- return -EINVAL;
-
- drm_dev = dev;
-
- list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
- subdrv->drm_dev = dev;
- err = exynos_drm_subdrv_probe(dev, subdrv);
- if (err) {
- DRM_DEBUG("exynos drm subdrv probe failed.\n");
- list_del(&subdrv->list);
- }
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(exynos_drm_device_register);
-
-int exynos_drm_device_unregister(struct drm_device *dev)
-{
- struct exynos_drm_subdrv *subdrv;
-
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (!dev) {
- WARN(1, "Unexpected drm device unregister!\n");
- return -EINVAL;
- }
-
- list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list)
- exynos_drm_subdrv_remove(dev, subdrv);
-
- drm_dev = NULL;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
-
-int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (!subdrv)
- return -EINVAL;
-
- list_add_tail(&subdrv->list, &exynos_drm_subdrv_list);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
-
-int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (!subdrv)
- return -EINVAL;
-
- list_del(&subdrv->list);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister);
-
-int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
-{
- struct exynos_drm_subdrv *subdrv;
- int ret;
-
- list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
- if (subdrv->open) {
- ret = subdrv->open(dev, subdrv->dev, file);
- if (ret)
- goto err;
- }
- }
-
- return 0;
-
-err:
- list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
- if (subdrv->close)
- subdrv->close(dev, subdrv->dev, file);
- }
- return ret;
-}
-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_open);
-
-void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
-{
- struct exynos_drm_subdrv *subdrv;
-
- list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
- if (subdrv->close)
- subdrv->close(dev, subdrv->dev, file);
- }
-}
-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_crtc.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_crtc.c
deleted file mode 100644
index 4afb625..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_crtc.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/* exynos_drm_crtc.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm_crtc_helper.h"
-
-#include "exynos_drm_crtc.h"
-#include "exynos_drm_drv.h"
-#include "exynos_drm_fb.h"
-#include "exynos_drm_encoder.h"
-#include "exynos_drm_gem.h"
-
-#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\
- drm_crtc)
-
-/*
- * Exynos specific crtc structure.
- *
- * @drm_crtc: crtc object.
- * @overlay: contain information common to display controller and hdmi and
- * contents of this overlay object would be copied to sub driver size.
- * @pipe: a crtc index created at load() with a new crtc object creation
- * and the crtc object would be set to private->crtc array
- * to get a crtc object corresponding to this pipe from private->crtc
- * array when irq interrupt occured. the reason of using this pipe is that
- * drm framework doesn't support multiple irq yet.
- * we can refer to the crtc to current hardware interrupt occured through
- * this pipe value.
- * @dpms: store the crtc dpms value
- */
-struct exynos_drm_crtc {
- struct drm_crtc drm_crtc;
- struct exynos_drm_overlay overlay;
- unsigned int pipe;
- unsigned int dpms;
-};
-
-static void exynos_drm_crtc_apply(struct drm_crtc *crtc)
-{
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- struct exynos_drm_overlay *overlay = &exynos_crtc->overlay;
-
- exynos_drm_fn_encoder(crtc, overlay,
- exynos_drm_encoder_crtc_mode_set);
- exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
- exynos_drm_encoder_crtc_commit);
-}
-
-int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
- struct drm_framebuffer *fb,
- struct drm_display_mode *mode,
- struct exynos_drm_crtc_pos *pos)
-{
- struct exynos_drm_gem_buf *buffer;
- unsigned int actual_w;
- unsigned int actual_h;
- int nr = exynos_drm_format_num_buffers(fb->pixel_format);
- int i;
-
- for (i = 0; i < nr; i++) {
- buffer = exynos_drm_fb_buffer(fb, i);
- if (!buffer) {
- DRM_LOG_KMS("buffer is null\n");
- return -EFAULT;
- }
-
- overlay->dma_addr[i] = buffer->dma_addr;
- overlay->vaddr[i] = buffer->kvaddr;
-
- DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n",
- i, (unsigned long)overlay->vaddr[i],
- (unsigned long)overlay->dma_addr[i]);
- }
-
- actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
- actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
-
- /* set drm framebuffer data. */
- overlay->fb_x = pos->fb_x;
- overlay->fb_y = pos->fb_y;
- overlay->fb_width = fb->width;
- overlay->fb_height = fb->height;
- overlay->src_width = pos->src_w;
- overlay->src_height = pos->src_h;
- overlay->bpp = fb->bits_per_pixel;
- overlay->pitch = fb->pitches[0];
- overlay->pixel_format = fb->pixel_format;
-
- /* set overlay range to be displayed. */
- overlay->crtc_x = pos->crtc_x;
- overlay->crtc_y = pos->crtc_y;
- overlay->crtc_width = actual_w;
- overlay->crtc_height = actual_h;
-
- /* set drm mode data. */
- overlay->mode_width = mode->hdisplay;
- overlay->mode_height = mode->vdisplay;
- overlay->refresh = mode->vrefresh;
- overlay->scan_flag = mode->flags;
-
- DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
- overlay->crtc_x, overlay->crtc_y,
- overlay->crtc_width, overlay->crtc_height);
-
- return 0;
-}
-
-static int exynos_drm_crtc_update(struct drm_crtc *crtc)
-{
- struct exynos_drm_crtc *exynos_crtc;
- struct exynos_drm_overlay *overlay;
- struct exynos_drm_crtc_pos pos;
- struct drm_display_mode *mode = &crtc->mode;
- struct drm_framebuffer *fb = crtc->fb;
-
- if (!mode || !fb)
- return -EINVAL;
-
- exynos_crtc = to_exynos_crtc(crtc);
- overlay = &exynos_crtc->overlay;
-
- memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos));
-
- /* it means the offset of framebuffer to be displayed. */
- pos.fb_x = crtc->x;
- pos.fb_y = crtc->y;
-
- /* OSD position to be displayed. */
- pos.crtc_x = 0;
- pos.crtc_y = 0;
- pos.crtc_w = fb->width - crtc->x;
- pos.crtc_h = fb->height - crtc->y;
- pos.src_w = pos.crtc_w;
- pos.src_h = pos.crtc_h;
-
- return exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos);
-}
-
-static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct drm_device *dev = crtc->dev;
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-
- DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
-
- if (exynos_crtc->dpms == mode) {
- DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
- return;
- }
-
- mutex_lock(&dev->struct_mutex);
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- exynos_drm_fn_encoder(crtc, &mode,
- exynos_drm_encoder_crtc_dpms);
- exynos_crtc->dpms = mode;
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- exynos_drm_fn_encoder(crtc, &mode,
- exynos_drm_encoder_crtc_dpms);
- exynos_crtc->dpms = mode;
- break;
- default:
- DRM_ERROR("unspecified mode %d\n", mode);
- break;
- }
-
- mutex_unlock(&dev->struct_mutex);
-}
-
-static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* drm framework doesn't check NULL. */
-}
-
-static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
-{
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * when set_crtc is requested from user or at booting time,
- * crtc->commit would be called without dpms call so if dpms is
- * no power on then crtc->dpms should be called
- * with DRM_MODE_DPMS_ON for the hardware power to be on.
- */
- if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) {
- int mode = DRM_MODE_DPMS_ON;
-
- /*
- * enable hardware(power on) to all encoders hdmi connected
- * to current crtc.
- */
- exynos_drm_crtc_dpms(crtc, mode);
- /*
- * enable dma to all encoders connected to current crtc and
- * lcd panel.
- */
- exynos_drm_fn_encoder(crtc, &mode,
- exynos_drm_encoder_dpms_from_crtc);
- }
-
- exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
- exynos_drm_encoder_crtc_commit);
-}
-
-static bool
-exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* drm framework doesn't check NULL */
- return true;
-}
-
-static int
-exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode, int x, int y,
- struct drm_framebuffer *old_fb)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * copy the mode data adjusted by mode_fixup() into crtc->mode
- * so that hardware can be seet to proper mode.
- */
- memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
-
- return exynos_drm_crtc_update(crtc);
-}
-
-static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb)
-{
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- ret = exynos_drm_crtc_update(crtc);
- if (ret)
- return ret;
-
- exynos_drm_crtc_apply(crtc);
-
- return ret;
-}
-
-static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
- /* drm framework doesn't check NULL */
-}
-
-static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
- .dpms = exynos_drm_crtc_dpms,
- .prepare = exynos_drm_crtc_prepare,
- .commit = exynos_drm_crtc_commit,
- .mode_fixup = exynos_drm_crtc_mode_fixup,
- .mode_set = exynos_drm_crtc_mode_set,
- .mode_set_base = exynos_drm_crtc_mode_set_base,
- .load_lut = exynos_drm_crtc_load_lut,
-};
-
-static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event)
-{
- struct drm_device *dev = crtc->dev;
- struct exynos_drm_private *dev_priv = dev->dev_private;
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- struct drm_framebuffer *old_fb = crtc->fb;
- int ret = -EINVAL;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- mutex_lock(&dev->struct_mutex);
-
- if (event) {
- /*
- * the pipe from user always is 0 so we can set pipe number
- * of current owner to event.
- */
- event->pipe = exynos_crtc->pipe;
-
- ret = drm_vblank_get(dev, exynos_crtc->pipe);
- if (ret) {
- DRM_DEBUG("failed to acquire vblank counter\n");
- list_del(&event->base.link);
-
- goto out;
- }
-
- list_add_tail(&event->base.link,
- &dev_priv->pageflip_event_list);
-
- crtc->fb = fb;
- ret = exynos_drm_crtc_update(crtc);
- if (ret) {
- crtc->fb = old_fb;
- drm_vblank_put(dev, exynos_crtc->pipe);
- list_del(&event->base.link);
-
- goto out;
- }
-
- /*
- * the values related to a buffer of the drm framebuffer
- * to be applied should be set at here. because these values
- * first, are set to shadow registers and then to
- * real registers at vsync front porch period.
- */
- exynos_drm_crtc_apply(crtc);
- }
-out:
- mutex_unlock(&dev->struct_mutex);
- return ret;
-}
-
-static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
-{
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- struct exynos_drm_private *private = crtc->dev->dev_private;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- private->crtc[exynos_crtc->pipe] = NULL;
-
- drm_crtc_cleanup(crtc);
- kfree(exynos_crtc);
-}
-
-static struct drm_crtc_funcs exynos_crtc_funcs = {
- .set_config = drm_crtc_helper_set_config,
- .page_flip = exynos_drm_crtc_page_flip,
- .destroy = exynos_drm_crtc_destroy,
-};
-
-struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev,
- struct drm_crtc *crtc)
-{
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-
- return &exynos_crtc->overlay;
-}
-
-int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
-{
- struct exynos_drm_crtc *exynos_crtc;
- struct exynos_drm_private *private = dev->dev_private;
- struct drm_crtc *crtc;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
- if (!exynos_crtc) {
- DRM_ERROR("failed to allocate exynos crtc\n");
- return -ENOMEM;
- }
-
- exynos_crtc->pipe = nr;
- exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
- exynos_crtc->overlay.zpos = DEFAULT_ZPOS;
- crtc = &exynos_crtc->drm_crtc;
-
- private->crtc[nr] = crtc;
-
- drm_crtc_init(dev, crtc, &exynos_crtc_funcs);
- drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
-
- return 0;
-}
-
-int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
-{
- struct exynos_drm_private *private = dev->dev_private;
- struct exynos_drm_crtc *exynos_crtc =
- to_exynos_crtc(private->crtc[crtc]);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
- return -EPERM;
-
- exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
- exynos_drm_enable_vblank);
-
- return 0;
-}
-
-void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
-{
- struct exynos_drm_private *private = dev->dev_private;
- struct exynos_drm_crtc *exynos_crtc =
- to_exynos_crtc(private->crtc[crtc]);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
- return;
-
- exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
- exynos_drm_disable_vblank);
-}
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_crtc.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_crtc.h
deleted file mode 100644
index 16b8e21..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_crtc.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* exynos_drm_crtc.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_CRTC_H_
-#define _EXYNOS_DRM_CRTC_H_
-
-struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev,
- struct drm_crtc *crtc);
-int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
-int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
-void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
-
-/*
- * Exynos specific crtc postion structure.
- *
- * @fb_x: offset x on a framebuffer to be displyed
- * - the unit is screen coordinates.
- * @fb_y: offset y on a framebuffer to be displayed
- * - the unit is screen coordinates.
- * @src_w: width of source area to be displayed from a framebuffer.
- * @src_h: height of source area to be displayed from a framebuffer.
- * @crtc_x: offset x on hardware screen.
- * @crtc_y: offset y on hardware screen.
- * @crtc_w: width of hardware screen.
- * @crtc_h: height of hardware screen.
- */
-struct exynos_drm_crtc_pos {
- unsigned int fb_x;
- unsigned int fb_y;
- unsigned int src_w;
- unsigned int src_h;
- unsigned int crtc_x;
- unsigned int crtc_y;
- unsigned int crtc_w;
- unsigned int crtc_h;
-};
-
-int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
- struct drm_framebuffer *fb,
- struct drm_display_mode *mode,
- struct exynos_drm_crtc_pos *pos);
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_dmabuf.c
deleted file mode 100644
index 9b97057..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_dmabuf.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/* exynos_drm_dmabuf.c
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * Author: Inki Dae <inki.dae@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "exynos_drm_drv.h"
-#include "exynos_drm_gem.h"
-
-#include <linux/dma-buf.h>
-
-static struct sg_table *exynos_pages_to_sg(struct page **pages, int nr_pages,
- unsigned int page_size)
-{
- struct sg_table *sgt = NULL;
- struct scatterlist *sgl;
- int i, ret;
-
- sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
- if (!sgt)
- goto out;
-
- ret = sg_alloc_table(sgt, nr_pages, GFP_KERNEL);
- if (ret)
- goto err_free_sgt;
-
- if (page_size < PAGE_SIZE)
- page_size = PAGE_SIZE;
-
- for_each_sg(sgt->sgl, sgl, nr_pages, i)
- sg_set_page(sgl, pages[i], page_size, 0);
-
- return sgt;
-
-err_free_sgt:
- kfree(sgt);
- sgt = NULL;
-out:
- return NULL;
-}
-
-static struct sg_table *exynos_gem_map_dma_buf(
- struct dma_buf_attachment *attach,
- enum dma_data_direction dir)
-{
- struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv;
- struct drm_device *dev = gem_obj->base.dev;
- struct exynos_drm_gem_buf *buf;
- struct sg_table *sgt = NULL;
- unsigned int npages;
- int nents;
-
- DRM_DEBUG_PRIME("%s\n", __FILE__);
-
- mutex_lock(&dev->struct_mutex);
-
- buf = gem_obj->buffer;
-
- /* there should always be pages allocated. */
- if (!buf->pages) {
- DRM_ERROR("pages is null.\n");
- goto err_unlock;
- }
-
- npages = buf->size / buf->page_size;
-
- sgt = exynos_pages_to_sg(buf->pages, npages, buf->page_size);
- nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir);
-
- DRM_DEBUG_PRIME("npages = %d buffer size = 0x%lx page_size = 0x%lx\n",
- npages, buf->size, buf->page_size);
-
-err_unlock:
- mutex_unlock(&dev->struct_mutex);
- return sgt;
-}
-
-static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
- struct sg_table *sgt,
- enum dma_data_direction dir)
-{
- dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
- sg_free_table(sgt);
- kfree(sgt);
- sgt = NULL;
-}
-
-static void exynos_dmabuf_release(struct dma_buf *dmabuf)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj = dmabuf->priv;
-
- DRM_DEBUG_PRIME("%s\n", __FILE__);
-
- /*
- * exynos_dmabuf_release() call means that file object's
- * f_count is 0 and it calls drm_gem_object_handle_unreference()
- * to drop the references that these values had been increased
- * at drm_prime_handle_to_fd()
- */
- if (exynos_gem_obj->base.export_dma_buf == dmabuf) {
- exynos_gem_obj->base.export_dma_buf = NULL;
-
- /*
- * drop this gem object refcount to release allocated buffer
- * and resources.
- */
- drm_gem_object_unreference_unlocked(&exynos_gem_obj->base);
- }
-}
-
-static void *exynos_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
- unsigned long page_num)
-{
- return NULL;
-}
-
-static void exynos_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
- unsigned long page_num,
- void *addr)
-{
-
-}
-
-static void *exynos_gem_dmabuf_kmap(struct dma_buf *dma_buf,
- unsigned long page_num)
-{
- return NULL;
-}
-
-static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf,
- unsigned long page_num, void *addr)
-{
-
-}
-
-static struct dma_buf_ops exynos_dmabuf_ops = {
- .map_dma_buf = exynos_gem_map_dma_buf,
- .unmap_dma_buf = exynos_gem_unmap_dma_buf,
- .kmap = exynos_gem_dmabuf_kmap,
- .kmap_atomic = exynos_gem_dmabuf_kmap_atomic,
- .kunmap = exynos_gem_dmabuf_kunmap,
- .kunmap_atomic = exynos_gem_dmabuf_kunmap_atomic,
- .release = exynos_dmabuf_release,
-};
-
-struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,
- struct drm_gem_object *obj, int flags)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
-
- return dma_buf_export(exynos_gem_obj, &exynos_dmabuf_ops,
- exynos_gem_obj->base.size, 0600);
-}
-
-struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
- struct dma_buf *dma_buf)
-{
- struct dma_buf_attachment *attach;
- struct sg_table *sgt;
- struct scatterlist *sgl;
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct exynos_drm_gem_buf *buffer;
- struct page *page;
- int ret;
-
- DRM_DEBUG_PRIME("%s\n", __FILE__);
-
- /* is this one of own objects? */
- if (dma_buf->ops == &exynos_dmabuf_ops) {
- struct drm_gem_object *obj;
-
- exynos_gem_obj = dma_buf->priv;
- obj = &exynos_gem_obj->base;
-
- /* is it from our device? */
- if (obj->dev == drm_dev) {
- drm_gem_object_reference(obj);
- return obj;
- }
- }
-
- attach = dma_buf_attach(dma_buf, drm_dev->dev);
- if (IS_ERR(attach))
- return ERR_PTR(-EINVAL);
-
-
- sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
- if (IS_ERR(sgt)) {
- ret = PTR_ERR(sgt);
- goto err_buf_detach;
- }
-
- buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
- if (!buffer) {
- DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
- ret = -ENOMEM;
- goto err_unmap_attach;
- }
-
- buffer->pages = kzalloc(sizeof(*page) * sgt->nents, GFP_KERNEL);
- if (!buffer->pages) {
- DRM_ERROR("failed to allocate pages.\n");
- ret = -ENOMEM;
- goto err_free_buffer;
- }
-
- exynos_gem_obj = exynos_drm_gem_init(drm_dev, dma_buf->size);
- if (!exynos_gem_obj) {
- ret = -ENOMEM;
- goto err_free_pages;
- }
-
- sgl = sgt->sgl;
-
- if (sgt->nents == 1) {
- buffer->dma_addr = sg_dma_address(sgt->sgl);
- buffer->size = sg_dma_len(sgt->sgl);
- } else {
- unsigned int i = 0;
-
- buffer->dma_addr = sg_dma_address(sgl);
- while (i < sgt->nents) {
- buffer->pages[i] = sg_page(sgl);
- buffer->size += sg_dma_len(sgl);
- sgl = sg_next(sgl);
- i++;
- }
- }
-
- exynos_gem_obj->buffer = buffer;
- buffer->sgt = sgt;
- exynos_gem_obj->base.import_attach = attach;
-
- /* register buffer information to private buffer manager. */
- ret = register_buf_to_priv_mgr(exynos_gem_obj,
- &exynos_gem_obj->priv_handle,
- &exynos_gem_obj->priv_id);
- if (ret < 0)
- goto err_release_gem;
-
- DRM_DEBUG_PRIME("ump id = %d, dma_addr = 0x%x, size = 0x%lx\n",
- exynos_gem_obj->priv_id,
- buffer->dma_addr,
- buffer->size);
-
- return &exynos_gem_obj->base;
-
-err_release_gem:
- drm_gem_object_release(&exynos_gem_obj->base);
- kfree(exynos_gem_obj);
- exynos_gem_obj = NULL;
-err_free_pages:
- kfree(buffer->pages);
- buffer->pages = NULL;
-err_free_buffer:
- kfree(buffer);
- buffer = NULL;
-err_unmap_attach:
- dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
-err_buf_detach:
- dma_buf_detach(dma_buf, attach);
- return ERR_PTR(ret);
-}
-
-MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC DRM DMABUF Module");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_dmabuf.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_dmabuf.h
deleted file mode 100644
index 662a8f9..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_dmabuf.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* exynos_drm_dmabuf.h
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * Author: Inki Dae <inki.dae@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_DMABUF_H_
-#define _EXYNOS_DRM_DMABUF_H_
-
-#ifdef CONFIG_DRM_EXYNOS_DMABUF
-struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,
- struct drm_gem_object *obj, int flags);
-
-struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
- struct dma_buf *dma_buf);
-#else
-#define exynos_dmabuf_prime_export NULL
-#define exynos_dmabuf_prime_import NULL
-#endif
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_drv.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_drv.c
deleted file mode 100644
index 340a8d6..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_drv.c
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "drm_crtc_helper.h"
-
-#include <drm/exynos_drm.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_crtc.h"
-#include "exynos_drm_encoder.h"
-#include "exynos_drm_fbdev.h"
-#include "exynos_drm_fb.h"
-#include "exynos_drm_gem.h"
-#include "exynos_drm_g2d.h"
-#include "exynos_drm_rotator.h"
-#include "exynos_drm_plane.h"
-#include "exynos_drm_vidi.h"
-#include "exynos_drm_dmabuf.h"
-
-#define DRIVER_NAME "exynos-drm"
-#define DRIVER_DESC "Samsung SoC DRM"
-#define DRIVER_DATE "20110530"
-#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 0
-
-#define VBLANK_OFF_DELAY 50000
-
-static int exynos_drm_list_gem_info(int id, void *ptr, void *data)
-{
- struct drm_gem_object *obj = ptr;
- struct drm_file *filp = data;
- struct exynos_drm_gem_obj *gem = to_exynos_gem_obj(obj);
- struct exynos_drm_gem_buf *buf = gem->buffer;
-
- DRM_INFO("%3d \t%3d \t%2d \t\t%2d \t0x%lx \t0x%x \t0x%lx "\
- "\t%2d \t\t%2d \t\t%2d\n",
- filp->pid,
- id,
- atomic_read(&obj->refcount.refcount),
- atomic_read(&obj->handle_count),
- gem->size,
- gem->flags,
- buf->page_size,
- buf->pfnmap,
- obj->export_dma_buf ? 1 : 0,
- obj->import_attach ? 1 : 0);
-
- return 0;
-}
-
-static ssize_t exynos_drm_show_gem_info(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct drm_device *drm_dev = dev_get_drvdata(dev);
- struct drm_file *filp;
-
- DRM_INFO("pid \thandle \trefcount \thcount \tsize \t\tflags "\
- "\tpage_size \tpfnmap \texport_to_fd \timport_from_fd\n");
-
- list_for_each_entry(filp, &drm_dev->filelist, lhead)
- idr_for_each(&filp->object_idr, &exynos_drm_list_gem_info,
- filp);
-
- return strlen(buf);
-}
-
-static const struct device_attribute exynos_device_attrs[] = {
- __ATTR(gem_info, S_IRUGO, exynos_drm_show_gem_info, NULL)
-};
-
-static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
-{
- struct exynos_drm_private *private;
- int ret;
- int nr;
-
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
- if (!private) {
- DRM_ERROR("failed to allocate private\n");
- return -ENOMEM;
- }
-
- INIT_LIST_HEAD(&private->pageflip_event_list);
- dev->dev_private = (void *)private;
-
- drm_mode_config_init(dev);
-
- /* init kms poll for handling hpd */
- drm_kms_helper_poll_init(dev);
-
- exynos_drm_mode_config_init(dev);
-
- /*
- * EXYNOS4 is enough to have two CRTCs and each crtc would be used
- * without dependency of hardware.
- */
- for (nr = 0; nr < MAX_CRTC; nr++) {
- ret = exynos_drm_crtc_create(dev, nr);
- if (ret)
- goto err_crtc;
- }
-
- for (nr = 0; nr < MAX_PLANE; nr++) {
- ret = exynos_plane_init(dev, nr);
- if (ret)
- goto err_crtc;
- }
-
- ret = drm_vblank_init(dev, MAX_CRTC);
- if (ret)
- goto err_crtc;
-
- /*
- * probe sub drivers such as display controller and hdmi driver,
- * that were registered at probe() of platform driver
- * to the sub driver and create encoder and connector for them.
- */
- ret = exynos_drm_device_register(dev);
- if (ret)
- goto err_vblank;
-
- /* setup possible_clones. */
- exynos_drm_encoder_setup(dev);
-
- /*
- * create and configure fb helper and also exynos specific
- * fbdev object.
- */
- ret = exynos_drm_fbdev_init(dev);
- if (ret) {
- DRM_ERROR("failed to initialize drm fbdev\n");
- goto err_drm_device;
- }
-
- drm_vblank_offdelay = VBLANK_OFF_DELAY;
-
- ret = device_create_file(dev->dev, &exynos_device_attrs[0]);
- if (ret < 0)
- DRM_DEBUG_DRIVER("failed to create sysfs.\n");
-
- return 0;
-
-err_drm_device:
- exynos_drm_device_unregister(dev);
-err_vblank:
- drm_vblank_cleanup(dev);
-err_crtc:
- drm_mode_config_cleanup(dev);
- kfree(private);
-
- return ret;
-}
-
-static int exynos_drm_unload(struct drm_device *dev)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- exynos_drm_fbdev_fini(dev);
- exynos_drm_device_unregister(dev);
- drm_vblank_cleanup(dev);
- drm_kms_helper_poll_fini(dev);
- drm_mode_config_cleanup(dev);
- kfree(dev->dev_private);
-
- dev->dev_private = NULL;
-
- return 0;
-}
-
-static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
-{
- struct drm_exynos_file_private *file_priv;
-
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
- if (!file_priv)
- return -ENOMEM;
-
- drm_prime_init_file_private(&file->prime);
- file->driver_priv = file_priv;
-
- return exynos_drm_subdrv_open(dev, file);
-}
-
-static void exynos_drm_preclose(struct drm_device *dev,
- struct drm_file *file)
-{
- struct exynos_drm_private *private = dev->dev_private;
- struct drm_pending_vblank_event *e, *t;
- unsigned long flags;
-
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- /* release events of current file */
- spin_lock_irqsave(&dev->event_lock, flags);
- list_for_each_entry_safe(e, t, &private->pageflip_event_list,
- base.link) {
- if (e->base.file_priv == file) {
- list_del(&e->base.link);
- e->base.destroy(&e->base);
- }
- }
- drm_prime_destroy_file_private(&file->prime);
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
- exynos_drm_subdrv_close(dev, file);
-}
-
-static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- if (!file->driver_priv)
- return;
-
- kfree(file->driver_priv);
- file->driver_priv = NULL;
-}
-
-static void exynos_drm_lastclose(struct drm_device *dev)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- exynos_drm_fbdev_restore_mode(dev);
-}
-
-static struct vm_operations_struct exynos_drm_gem_vm_ops = {
- .fault = exynos_drm_gem_fault,
- .open = drm_gem_vm_open,
- .close = drm_gem_vm_close,
-};
-
-static struct drm_ioctl_desc exynos_ioctls[] = {
- DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
- DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET,
- exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP,
- exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(EXYNOS_GEM_USERPTR,
- exynos_drm_gem_userptr_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET,
- exynos_drm_gem_get_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(EXYNOS_GEM_EXPORT_UMP,
- exynos_drm_gem_export_ump_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CACHE_OP,
- exynos_drm_gem_cache_op_ioctl, DRM_UNLOCKED),
- /* temporary ioctl commands. */
- DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET_PHY,
- exynos_drm_gem_get_phy_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(EXYNOS_GEM_PHY_IMP,
- exynos_drm_gem_phy_imp_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS,
- exynos_plane_set_zpos_ioctl, DRM_UNLOCKED | DRM_AUTH),
- DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION,
- vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH),
-
- DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER,
- exynos_g2d_get_ver_ioctl, DRM_UNLOCKED | DRM_AUTH),
- DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST,
- exynos_g2d_set_cmdlist_ioctl, DRM_UNLOCKED | DRM_AUTH),
- DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC,
- exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH),
-
- DRM_IOCTL_DEF_DRV(EXYNOS_ROTATOR_EXEC,
- exynos_drm_rotator_exec_ioctl, DRM_UNLOCKED | DRM_AUTH),
-};
-
-static const struct file_operations exynos_drm_driver_fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .mmap = exynos_drm_gem_mmap,
- .poll = drm_poll,
- .read = drm_read,
- .unlocked_ioctl = drm_ioctl,
- .release = drm_release,
-};
-
-static struct drm_driver exynos_drm_driver = {
- .driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM |
- DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
- .load = exynos_drm_load,
- .unload = exynos_drm_unload,
- .open = exynos_drm_open,
- .preclose = exynos_drm_preclose,
- .lastclose = exynos_drm_lastclose,
- .postclose = exynos_drm_postclose,
- .get_vblank_counter = drm_vblank_count,
- .enable_vblank = exynos_drm_crtc_enable_vblank,
- .disable_vblank = exynos_drm_crtc_disable_vblank,
- .gem_init_object = exynos_drm_gem_init_object,
- .gem_free_object = exynos_drm_gem_free_object,
- .gem_vm_ops = &exynos_drm_gem_vm_ops,
- .gem_close_object = &exynos_drm_gem_close_object,
- .dumb_create = exynos_drm_gem_dumb_create,
- .dumb_map_offset = exynos_drm_gem_dumb_map_offset,
- .dumb_destroy = exynos_drm_gem_dumb_destroy,
- .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
- .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
- .gem_prime_export = exynos_dmabuf_prime_export,
- .gem_prime_import = exynos_dmabuf_prime_import,
- .ioctls = exynos_ioctls,
- .fops = &exynos_drm_driver_fops,
- .name = DRIVER_NAME,
- .desc = DRIVER_DESC,
- .date = DRIVER_DATE,
- .major = DRIVER_MAJOR,
- .minor = DRIVER_MINOR,
-};
-
-static int exynos_drm_platform_probe(struct platform_device *pdev)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
-
- return drm_platform_init(&exynos_drm_driver, pdev);
-}
-
-static int exynos_drm_platform_remove(struct platform_device *pdev)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- drm_platform_exit(&exynos_drm_driver, pdev);
-
- return 0;
-}
-
-static struct platform_driver exynos_drm_platform_driver = {
- .probe = exynos_drm_platform_probe,
- .remove = __devexit_p(exynos_drm_platform_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "exynos-drm",
- },
-};
-
-static int __init exynos_drm_init(void)
-{
- int ret;
-
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
-#ifdef CONFIG_DRM_EXYNOS_FIMD
- ret = platform_driver_register(&fimd_driver);
- if (ret < 0)
- goto out_fimd;
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_HDMI
- ret = platform_driver_register(&hdmi_driver);
- if (ret < 0)
- goto out_hdmi;
- ret = platform_driver_register(&mixer_driver);
- if (ret < 0)
- goto out_mixer;
- ret = platform_driver_register(&exynos_drm_common_hdmi_driver);
- if (ret < 0)
- goto out_common_hdmi;
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_VIDI
- ret = platform_driver_register(&vidi_driver);
- if (ret < 0)
- goto out_vidi;
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_G2D
- ret = platform_driver_register(&g2d_driver);
- if (ret < 0)
- goto out_g2d;
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_ROTATOR
- ret = platform_driver_register(&rotator_driver);
- if (ret < 0)
- goto out_rotator;
-#endif
-
- ret = platform_driver_register(&exynos_drm_platform_driver);
- if (ret < 0)
- goto out;
-
- return 0;
-
-out:
-#ifdef CONFIG_DRM_EXYNOS_ROTATOR
- platform_driver_unregister(&rotator_driver);
-out_rotator:
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_G2D
- platform_driver_unregister(&g2d_driver);
-out_g2d:
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_VIDI
- platform_driver_unregister(&vidi_driver);
-out_vidi:
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_HDMI
- platform_driver_unregister(&exynos_drm_common_hdmi_driver);
-out_common_hdmi:
- platform_driver_unregister(&mixer_driver);
-out_mixer:
- platform_driver_unregister(&hdmi_driver);
-out_hdmi:
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_FIMD
- platform_driver_unregister(&fimd_driver);
-out_fimd:
-#endif
- return ret;
-}
-
-static void __exit exynos_drm_exit(void)
-{
- DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
- platform_driver_unregister(&exynos_drm_platform_driver);
-
-#ifdef CONFIG_DRM_EXYNOS_ROTATOR
- platform_driver_unregister(&rotator_driver);
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_G2D
- platform_driver_unregister(&g2d_driver);
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_VIDI
- platform_driver_unregister(&vidi_driver);
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_HDMI
- platform_driver_unregister(&exynos_drm_common_hdmi_driver);
- platform_driver_unregister(&mixer_driver);
- platform_driver_unregister(&hdmi_driver);
-#endif
-
-#ifdef CONFIG_DRM_EXYNOS_FIMD
- platform_driver_unregister(&fimd_driver);
-#endif
-}
-
-module_init(exynos_drm_init);
-module_exit(exynos_drm_exit);
-
-MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
-MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
-MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC DRM Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_drv.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_drv.h
deleted file mode 100644
index 463b086..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_drv.h
+++ /dev/null
@@ -1,335 +0,0 @@
-/* exynos_drm_drv.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_DRV_H_
-#define _EXYNOS_DRM_DRV_H_
-
-#include <linux/module.h>
-#include "drm.h"
-
-#define MAX_CRTC 3
-#define MAX_PLANE 5
-#define MAX_FB_BUFFER 4
-#define DEFAULT_ZPOS -1
-
-struct drm_device;
-struct exynos_drm_overlay;
-struct drm_connector;
-
-extern unsigned int drm_vblank_offdelay;
-
-/* this enumerates display type. */
-enum exynos_drm_output_type {
- EXYNOS_DISPLAY_TYPE_NONE,
- /* RGB or CPU Interface. */
- EXYNOS_DISPLAY_TYPE_LCD,
- /* HDMI Interface. */
- EXYNOS_DISPLAY_TYPE_HDMI,
- /* Virtual Display Interface. */
- EXYNOS_DISPLAY_TYPE_VIDI,
-};
-
-/*
- * Exynos drm overlay ops structure.
- *
- * @mode_set: copy drm overlay info to hw specific overlay info.
- * @commit: apply hardware specific overlay data to registers.
- * @disable: disable hardware specific overlay.
- */
-struct exynos_drm_overlay_ops {
- void (*mode_set)(struct device *subdrv_dev,
- struct exynos_drm_overlay *overlay);
- void (*commit)(struct device *subdrv_dev, int zpos);
- void (*disable)(struct device *subdrv_dev, int zpos);
-};
-
-/*
- * Exynos drm common overlay structure.
- *
- * @fb_x: offset x on a framebuffer to be displayed.
- * - the unit is screen coordinates.
- * @fb_y: offset y on a framebuffer to be displayed.
- * - the unit is screen coordinates.
- * @fb_width: width of a framebuffer.
- * @fb_height: height of a framebuffer.
- * @src_width: width of a partial image to be displayed from framebuffer.
- * @src_height: height of a partial image to be displayed from framebuffer.
- * @crtc_x: offset x on hardware screen.
- * @crtc_y: offset y on hardware screen.
- * @crtc_width: window width to be displayed (hardware screen).
- * @crtc_height: window height to be displayed (hardware screen).
- * @mode_width: width of screen mode.
- * @mode_height: height of screen mode.
- * @refresh: refresh rate.
- * @scan_flag: interlace or progressive way.
- * (it could be DRM_MODE_FLAG_*)
- * @bpp: pixel size.(in bit)
- * @pixel_format: fourcc pixel format of this overlay
- * @dma_addr: array of bus(accessed by dma) address to the memory region
- * allocated for a overlay.
- * @vaddr: array of virtual memory addresss to this overlay.
- * @zpos: order of overlay layer(z position).
- * @default_win: a window to be enabled.
- * @color_key: color key on or off.
- * @index_color: if using color key feature then this value would be used
- * as index color.
- * @local_path: in case of lcd type, local path mode on or off.
- * @transparency: transparency on or off.
- * @activated: activated or not.
- *
- * this structure is common to exynos SoC and its contents would be copied
- * to hardware specific overlay info.
- */
-struct exynos_drm_overlay {
- unsigned int fb_x;
- unsigned int fb_y;
- unsigned int fb_width;
- unsigned int fb_height;
- unsigned int src_width;
- unsigned int src_height;
- unsigned int crtc_x;
- unsigned int crtc_y;
- unsigned int crtc_width;
- unsigned int crtc_height;
- unsigned int mode_width;
- unsigned int mode_height;
- unsigned int refresh;
- unsigned int scan_flag;
- unsigned int bpp;
- unsigned int pitch;
- uint32_t pixel_format;
- dma_addr_t dma_addr[MAX_FB_BUFFER];
- void __iomem *vaddr[MAX_FB_BUFFER];
- int zpos;
-
- bool default_win;
- bool color_key;
- unsigned int index_color;
- bool local_path;
- bool transparency;
- bool activated;
-};
-
-/*
- * Exynos DRM Display Structure.
- * - this structure is common to analog tv, digital tv and lcd panel.
- *
- * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
- * @is_connected: check for that display is connected or not.
- * @get_edid: get edid modes from display driver.
- * @get_panel: get panel object from display driver.
- * @check_timing: check if timing is valid or not.
- * @power_on: display device on or off.
- */
-struct exynos_drm_display_ops {
- enum exynos_drm_output_type type;
- bool (*is_connected)(struct device *dev);
- int (*get_edid)(struct device *dev, struct drm_connector *connector,
- u8 *edid, int len);
- void *(*get_panel)(struct device *dev);
- int (*check_timing)(struct device *dev, void *timing);
- int (*power_on)(struct device *dev, int mode);
-};
-
-/*
- * Exynos drm manager ops
- *
- * @dpms: control device power.
- * @apply: set timing, vblank and overlay data to registers.
- * @mode_fixup: fix mode data comparing to hw specific display mode.
- * @mode_set: convert drm_display_mode to hw specific display mode and
- * would be called by encoder->mode_set().
- * @get_max_resol: get maximum resolution to specific hardware.
- * @commit: set current hw specific display mode to hw.
- * @enable_vblank: specific driver callback for enabling vblank interrupt.
- * @disable_vblank: specific driver callback for disabling vblank interrupt.
- */
-struct exynos_drm_manager_ops {
- void (*dpms)(struct device *subdrv_dev, int mode);
- void (*apply)(struct device *subdrv_dev);
- void (*mode_fixup)(struct device *subdrv_dev,
- struct drm_connector *connector,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
- void (*mode_set)(struct device *subdrv_dev, void *mode);
- void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width,
- unsigned int *height);
- void (*commit)(struct device *subdrv_dev);
- int (*enable_vblank)(struct device *subdrv_dev);
- void (*disable_vblank)(struct device *subdrv_dev);
-};
-
-/*
- * Exynos drm common manager structure.
- *
- * @dev: pointer to device object for subdrv device driver.
- * sub drivers such as display controller or hdmi driver,
- * have their own device object.
- * @ops: pointer to callbacks for exynos drm specific framebuffer.
- * these callbacks should be set by specific drivers such fimd
- * or hdmi driver and are used to control hardware global registers.
- * @overlay_ops: pointer to callbacks for exynos drm specific framebuffer.
- * these callbacks should be set by specific drivers such fimd
- * or hdmi driver and are used to control hardware overlay reigsters.
- * @display: pointer to callbacks for exynos drm specific framebuffer.
- * these callbacks should be set by specific drivers such fimd
- * or hdmi driver and are used to control display devices such as
- * analog tv, digital tv and lcd panel and also get timing data for them.
- */
-struct exynos_drm_manager {
- struct device *dev;
- int pipe;
- struct exynos_drm_manager_ops *ops;
- struct exynos_drm_overlay_ops *overlay_ops;
- struct exynos_drm_display_ops *display_ops;
-};
-
-struct iommu_info_node {
- struct list_head list;
- dma_addr_t dma_addr;
- void *gem_obj;
- /* TODO */
-};
-
-/*
- * Exynos drm g2d private structure
- *
- * @dev: device object to device driver for using iommu.
- * @iommu_map_list: list head to iommu map information.
- * each device driver using iommu should have its own iommu_map_list
- * because device drivers have their own device address space and
- * the device address spaces could be duplicated echo other.
- */
-struct exynos_drm_g2d_private {
- struct device *dev;
- struct list_head inuse_cmdlist;
- struct list_head event_list;
- struct list_head iommu_map_list;
-};
-
-/*
- * Exynos drm rotator private structure
- *
- * @dev: device object to device driver for using driver data.
- * @iommu_list: list head to iommu map information.
- */
-struct exynos_drm_rot_private {
- struct device *dev;
- struct list_head iommu_list;
-};
-
-struct drm_exynos_file_private {
- struct exynos_drm_g2d_private *g2d_priv;
- struct exynos_drm_rot_private *rot_priv;
-};
-
-/*
- * Exynos drm private structure.
- */
-struct exynos_drm_private {
- struct drm_fb_helper *fb_helper;
-
- /* list head for new event to be added. */
- struct list_head pageflip_event_list;
-
- /*
- * created crtc object would be contained at this array and
- * this array is used to be aware of which crtc did it request vblank.
- */
- struct drm_crtc *crtc[MAX_CRTC];
-};
-
-/*
- * Exynos drm sub driver structure.
- *
- * @list: sub driver has its own list object to register to exynos drm driver.
- * @dev: pointer to device object for subdrv device driver.
- * @drm_dev: pointer to drm_device and this pointer would be set
- * when sub driver calls exynos_drm_subdrv_register().
- * @manager: subdrv has its own manager to control a hardware appropriately
- * and we can access a hardware drawing on this manager.
- * @probe: this callback would be called by exynos drm driver after
- * subdrv is registered to it.
- * @remove: this callback is used to release resources created
- * by probe callback.
- * @open: this would be called with drm device file open.
- * @close: this would be called with drm device file close.
- * @encoder: encoder object owned by this sub driver.
- * @connector: connector object owned by this sub driver.
- */
-struct exynos_drm_subdrv {
- struct list_head list;
- struct device *dev;
- struct drm_device *drm_dev;
- struct exynos_drm_manager *manager;
-
- int (*probe)(struct drm_device *drm_dev, struct device *dev);
- void (*remove)(struct drm_device *dev);
- int (*open)(struct drm_device *drm_dev, struct device *dev,
- struct drm_file *file);
- void (*close)(struct drm_device *drm_dev, struct device *dev,
- struct drm_file *file);
-
- struct drm_encoder *encoder;
- struct drm_connector *connector;
-};
-
-/*
- * this function calls a probe callback registered to sub driver list and
- * create its own encoder and connector and then set drm_device object
- * to global one.
- */
-int exynos_drm_device_register(struct drm_device *dev);
-/*
- * this function calls a remove callback registered to sub driver list and
- * destroy its own encoder and connetor.
- */
-int exynos_drm_device_unregister(struct drm_device *dev);
-
-/*
- * this function would be called by sub drivers such as display controller
- * or hdmi driver to register this sub driver object to exynos drm driver
- * and when a sub driver is registered to exynos drm driver a probe callback
- * of the sub driver is called and creates its own encoder and connector.
- */
-int exynos_drm_subdrv_register(struct exynos_drm_subdrv *drm_subdrv);
-
-/* this function removes subdrv list from exynos drm driver */
-int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *drm_subdrv);
-
-int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file);
-void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file);
-
-extern struct platform_driver fimd_driver;
-extern struct platform_driver hdmi_driver;
-extern struct platform_driver mixer_driver;
-extern struct platform_driver exynos_drm_common_hdmi_driver;
-extern struct platform_driver vidi_driver;
-extern struct platform_driver g2d_driver;
-extern struct platform_driver rotator_driver;
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_encoder.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_encoder.c
deleted file mode 100644
index 6e9ac7b..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_encoder.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/* exynos_drm_encoder.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm_crtc_helper.h"
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_crtc.h"
-#include "exynos_drm_encoder.h"
-
-#define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder,\
- drm_encoder)
-
-/*
- * exynos specific encoder structure.
- *
- * @drm_encoder: encoder object.
- * @manager: specific encoder has its own manager to control a hardware
- * appropriately and we can access a hardware drawing on this manager.
- * @dpms: store the encoder dpms value.
- */
-struct exynos_drm_encoder {
- struct drm_encoder drm_encoder;
- struct exynos_drm_manager *manager;
- int dpms;
-};
-
-static void exynos_drm_display_power(struct drm_encoder *encoder, int mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_connector *connector;
- struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder) {
- struct exynos_drm_display_ops *display_ops =
- manager->display_ops;
-
- DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
- connector->base.id, mode);
- if (display_ops && display_ops->power_on)
- display_ops->power_on(manager->dev, mode);
- }
- }
-}
-
-static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
- struct drm_device *dev = encoder->dev;
- struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
- struct exynos_drm_manager_ops *manager_ops = manager->ops;
- struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
-
- DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
-
- if (exynos_encoder->dpms == mode) {
- DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
- return;
- }
-
- mutex_lock(&dev->struct_mutex);
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- if (manager_ops && manager_ops->apply)
- manager_ops->apply(manager->dev);
- exynos_drm_display_power(encoder, mode);
- exynos_encoder->dpms = mode;
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- exynos_drm_display_power(encoder, mode);
- exynos_encoder->dpms = mode;
- break;
- default:
- DRM_ERROR("unspecified mode %d\n", mode);
- break;
- }
-
- mutex_unlock(&dev->struct_mutex);
-}
-
-static bool
-exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_connector *connector;
- struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
- struct exynos_drm_manager_ops *manager_ops = manager->ops;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder)
- if (manager_ops && manager_ops->mode_fixup)
- manager_ops->mode_fixup(manager->dev, connector,
- mode, adjusted_mode);
- }
-
- return true;
-}
-
-static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_connector *connector;
- struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
- struct exynos_drm_manager_ops *manager_ops = manager->ops;
- struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- struct exynos_drm_overlay *overlay = get_exynos_drm_overlay(dev,
- encoder->crtc);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder) {
- if (manager_ops && manager_ops->mode_set)
- manager_ops->mode_set(manager->dev,
- adjusted_mode);
-
- if (overlay_ops && overlay_ops->mode_set)
- overlay_ops->mode_set(manager->dev, overlay);
- }
- }
-}
-
-static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* drm framework doesn't check NULL. */
-}
-
-static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
-{
- struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
- struct exynos_drm_manager_ops *manager_ops = manager->ops;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (manager_ops && manager_ops->commit)
- manager_ops->commit(manager->dev);
-}
-
-static struct drm_crtc *
-exynos_drm_encoder_get_crtc(struct drm_encoder *encoder)
-{
- return encoder->crtc;
-}
-
-static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
- .dpms = exynos_drm_encoder_dpms,
- .mode_fixup = exynos_drm_encoder_mode_fixup,
- .mode_set = exynos_drm_encoder_mode_set,
- .prepare = exynos_drm_encoder_prepare,
- .commit = exynos_drm_encoder_commit,
- .get_crtc = exynos_drm_encoder_get_crtc,
-};
-
-static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
-{
- struct exynos_drm_encoder *exynos_encoder =
- to_exynos_encoder(encoder);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_encoder->manager->pipe = -1;
-
- drm_encoder_cleanup(encoder);
- kfree(exynos_encoder);
-}
-
-static struct drm_encoder_funcs exynos_encoder_funcs = {
- .destroy = exynos_drm_encoder_destroy,
-};
-
-static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder)
-{
- struct drm_encoder *clone;
- struct drm_device *dev = encoder->dev;
- struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
- struct exynos_drm_display_ops *display_ops =
- exynos_encoder->manager->display_ops;
- unsigned int clone_mask = 0;
- int cnt = 0;
-
- list_for_each_entry(clone, &dev->mode_config.encoder_list, head) {
- switch (display_ops->type) {
- case EXYNOS_DISPLAY_TYPE_LCD:
- case EXYNOS_DISPLAY_TYPE_HDMI:
- case EXYNOS_DISPLAY_TYPE_VIDI:
- clone_mask |= (1 << (cnt++));
- break;
- default:
- continue;
- }
- }
-
- return clone_mask;
-}
-
-void exynos_drm_encoder_setup(struct drm_device *dev)
-{
- struct drm_encoder *encoder;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
- encoder->possible_clones = exynos_drm_encoder_clones(encoder);
-}
-
-struct drm_encoder *
-exynos_drm_encoder_create(struct drm_device *dev,
- struct exynos_drm_manager *manager,
- unsigned int possible_crtcs)
-{
- struct drm_encoder *encoder;
- struct exynos_drm_encoder *exynos_encoder;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!manager || !possible_crtcs)
- return NULL;
-
- if (!manager->dev)
- return NULL;
-
- exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
- if (!exynos_encoder) {
- DRM_ERROR("failed to allocate encoder\n");
- return NULL;
- }
-
- exynos_encoder->dpms = DRM_MODE_DPMS_OFF;
- exynos_encoder->manager = manager;
- encoder = &exynos_encoder->drm_encoder;
- encoder->possible_crtcs = possible_crtcs;
-
- DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
-
- drm_encoder_init(dev, encoder, &exynos_encoder_funcs,
- DRM_MODE_ENCODER_TMDS);
-
- drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
-
- DRM_DEBUG_KMS("encoder has been created\n");
-
- return encoder;
-}
-
-struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder)
-{
- return to_exynos_encoder(encoder)->manager;
-}
-
-void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
- void (*fn)(struct drm_encoder *, void *))
-{
- struct drm_device *dev = crtc->dev;
- struct drm_encoder *encoder;
- struct exynos_drm_private *private = dev->dev_private;
- struct exynos_drm_manager *manager;
-
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- /*
- * if crtc is detached from encoder, check pipe,
- * otherwise check crtc attached to encoder
- */
- if (!encoder->crtc) {
- manager = to_exynos_encoder(encoder)->manager;
- if (manager->pipe < 0 ||
- private->crtc[manager->pipe] != crtc)
- continue;
- } else {
- if (encoder->crtc != crtc)
- continue;
- }
-
- fn(encoder, data);
- }
-}
-
-void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
-{
- struct exynos_drm_manager *manager =
- to_exynos_encoder(encoder)->manager;
- struct exynos_drm_manager_ops *manager_ops = manager->ops;
- int crtc = *(int *)data;
-
- if (manager->pipe == -1)
- manager->pipe = crtc;
-
- if (manager_ops->enable_vblank)
- manager_ops->enable_vblank(manager->dev);
-}
-
-void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
-{
- struct exynos_drm_manager *manager =
- to_exynos_encoder(encoder)->manager;
- struct exynos_drm_manager_ops *manager_ops = manager->ops;
- int crtc = *(int *)data;
-
- if (manager->pipe == -1)
- manager->pipe = crtc;
-
- if (manager_ops->disable_vblank)
- manager_ops->disable_vblank(manager->dev);
-}
-
-void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder,
- void *data)
-{
- struct exynos_drm_manager *manager =
- to_exynos_encoder(encoder)->manager;
- struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- int zpos = DEFAULT_ZPOS;
-
- if (data)
- zpos = *(int *)data;
-
- if (overlay_ops && overlay_ops->commit)
- overlay_ops->commit(manager->dev, zpos);
-}
-
-void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data)
-{
- struct exynos_drm_manager *manager =
- to_exynos_encoder(encoder)->manager;
- int crtc = *(int *)data;
- int zpos = DEFAULT_ZPOS;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * when crtc is detached from encoder, this pipe is used
- * to select manager operation
- */
- manager->pipe = crtc;
-
- exynos_drm_encoder_crtc_plane_commit(encoder, &zpos);
-}
-
-void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, void *data)
-{
- struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
- int mode = *(int *)data;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_drm_encoder_dpms(encoder, mode);
-
- exynos_encoder->dpms = mode;
-}
-
-void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
-{
- struct drm_device *dev = encoder->dev;
- struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
- struct exynos_drm_manager *manager = exynos_encoder->manager;
- struct exynos_drm_manager_ops *manager_ops = manager->ops;
- struct drm_connector *connector;
- int mode = *(int *)data;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (manager_ops && manager_ops->dpms)
- manager_ops->dpms(manager->dev, mode);
-
- /*
- * set current dpms mode to the connector connected to
- * current encoder. connector->dpms would be checked
- * at drm_helper_connector_dpms()
- */
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- if (connector->encoder == encoder)
- connector->dpms = mode;
-
- /*
- * if this condition is ok then it means that the crtc is already
- * detached from encoder and last function for detaching is properly
- * done, so clear pipe from manager to prevent repeated call.
- */
- if (mode > DRM_MODE_DPMS_ON) {
- if (!encoder->crtc)
- manager->pipe = -1;
- }
-}
-
-void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
-{
- struct exynos_drm_manager *manager =
- to_exynos_encoder(encoder)->manager;
- struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- struct exynos_drm_overlay *overlay = data;
-
- if (overlay_ops && overlay_ops->mode_set)
- overlay_ops->mode_set(manager->dev, overlay);
-}
-
-void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data)
-{
- struct exynos_drm_manager *manager =
- to_exynos_encoder(encoder)->manager;
- struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- int zpos = DEFAULT_ZPOS;
-
- DRM_DEBUG_KMS("\n");
-
- if (data)
- zpos = *(int *)data;
-
- if (overlay_ops && overlay_ops->disable)
- overlay_ops->disable(manager->dev, zpos);
-}
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_encoder.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_encoder.h
deleted file mode 100644
index eb7d231..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_encoder.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_ENCODER_H_
-#define _EXYNOS_DRM_ENCODER_H_
-
-struct exynos_drm_manager;
-
-void exynos_drm_encoder_setup(struct drm_device *dev);
-struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev,
- struct exynos_drm_manager *mgr,
- unsigned int possible_crtcs);
-struct exynos_drm_manager *
-exynos_drm_get_manager(struct drm_encoder *encoder);
-void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
- void (*fn)(struct drm_encoder *, void *));
-void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data);
-void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder,
- void *data);
-void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder,
- void *data);
-void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data);
-
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_fb.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_fb.c
deleted file mode 100644
index 7b47330..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_fb.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/* exynos_drm_fb.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-#include "drm_fb_helper.h"
-
-#include "exynos_drm.h"
-#include "exynos_drm_drv.h"
-#include "exynos_drm_fb.h"
-#include "exynos_drm_gem.h"
-
-#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb)
-
-/*
- * exynos specific framebuffer structure.
- *
- * @fb: drm framebuffer obejct.
- * @exynos_gem_obj: array of exynos specific gem object containing a gem object.
- */
-struct exynos_drm_fb {
- struct drm_framebuffer fb;
- struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER];
-};
-
-static int check_fb_gem_memory_type(struct exynos_drm_gem_obj *exynos_gem_obj)
-{
- unsigned int flags;
-
- flags = exynos_gem_obj->flags;
-
- /* not support physically non-continuous memory for fb yet. TODO */
- if (IS_NONCONTIG_BUFFER(flags)) {
- DRM_ERROR("cannot use this gem memory type for fb.\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
-{
- struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- drm_framebuffer_cleanup(fb);
-
- kfree(exynos_fb);
- exynos_fb = NULL;
-}
-
-static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
- struct drm_file *file_priv,
- unsigned int *handle)
-{
- struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return drm_gem_handle_create(file_priv,
- &exynos_fb->exynos_gem_obj[0]->base, handle);
-}
-
-static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
- struct drm_file *file_priv, unsigned flags,
- unsigned color, struct drm_clip_rect *clips,
- unsigned num_clips)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO */
-
- return 0;
-}
-
-static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
- .destroy = exynos_drm_fb_destroy,
- .create_handle = exynos_drm_fb_create_handle,
- .dirty = exynos_drm_fb_dirty,
-};
-
-struct drm_framebuffer *
-exynos_drm_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd,
- struct drm_gem_object *obj)
-{
- struct exynos_drm_fb *exynos_fb;
- struct exynos_drm_gem_obj *exynos_gem_obj;
- int ret;
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- ret = check_fb_gem_memory_type(exynos_gem_obj);
- if (ret < 0) {
- DRM_ERROR("cannot use this gem memory type for fb.\n");
- return ERR_PTR(-EINVAL);
- }
-
- exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
- if (!exynos_fb) {
- DRM_ERROR("failed to allocate exynos drm framebuffer\n");
- return ERR_PTR(-ENOMEM);
- }
-
- exynos_fb->exynos_gem_obj[0] = exynos_gem_obj;
-
- ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
- if (ret) {
- DRM_ERROR("failed to initialize framebuffer\n");
- return ERR_PTR(ret);
- }
-
- drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
-
- return &exynos_fb->fb;
-}
-
-static struct drm_framebuffer *
-exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
-{
- struct drm_gem_object *obj;
- struct drm_framebuffer *fb;
- struct exynos_drm_fb *exynos_fb;
- int nr;
- int i;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object\n");
- return ERR_PTR(-ENOENT);
- }
-
- drm_gem_object_unreference_unlocked(obj);
-
- fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj);
- if (IS_ERR(fb))
- return fb;
-
- exynos_fb = to_exynos_fb(fb);
- nr = exynos_drm_format_num_buffers(fb->pixel_format);
-
- for (i = 1; i < nr; i++) {
- struct exynos_drm_gem_obj *exynos_gem_obj;
- int ret;
-
- obj = drm_gem_object_lookup(dev, file_priv,
- mode_cmd->handles[i]);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object\n");
- exynos_drm_fb_destroy(fb);
- return ERR_PTR(-ENOENT);
- }
-
- drm_gem_object_unreference_unlocked(obj);
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- ret = check_fb_gem_memory_type(exynos_gem_obj);
- if (ret < 0) {
- DRM_ERROR("cannot use this gem memory type for fb.\n");
- exynos_drm_fb_destroy(fb);
- return ERR_PTR(ret);
- }
-
- exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj);
- }
-
- return fb;
-}
-
-struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
- int index)
-{
- struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
- struct exynos_drm_gem_buf *buffer;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (index >= MAX_FB_BUFFER)
- return NULL;
-
- buffer = exynos_fb->exynos_gem_obj[index]->buffer;
- if (!buffer)
- return NULL;
-
- DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
- (unsigned long)buffer->kvaddr,
- (unsigned long)buffer->dma_addr);
-
- return buffer;
-}
-
-static void exynos_drm_output_poll_changed(struct drm_device *dev)
-{
- struct exynos_drm_private *private = dev->dev_private;
- struct drm_fb_helper *fb_helper = private->fb_helper;
-
- if (fb_helper)
- drm_fb_helper_hotplug_event(fb_helper);
-}
-
-static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
- .fb_create = exynos_user_fb_create,
- .output_poll_changed = exynos_drm_output_poll_changed,
-};
-
-void exynos_drm_mode_config_init(struct drm_device *dev)
-{
- dev->mode_config.min_width = 0;
- dev->mode_config.min_height = 0;
-
- /*
- * set max width and height as default value(4096x4096).
- * this value would be used to check framebuffer size limitation
- * at drm_mode_addfb().
- */
- dev->mode_config.max_width = 4096;
- dev->mode_config.max_height = 4096;
-
- dev->mode_config.funcs = &exynos_drm_mode_config_funcs;
-}
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_fb.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_fb.h
deleted file mode 100644
index 3ecb30d..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_fb.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_FB_H_
-#define _EXYNOS_DRM_FB_H
-
-static inline int exynos_drm_format_num_buffers(uint32_t format)
-{
- switch (format) {
- case DRM_FORMAT_NV12M:
- case DRM_FORMAT_NV12MT:
- return 2;
- case DRM_FORMAT_YUV420M:
- return 3;
- default:
- return 1;
- }
-}
-
-struct drm_framebuffer *
-exynos_drm_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd,
- struct drm_gem_object *obj);
-
-/* get memory information of a drm framebuffer */
-struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
- int index);
-
-void exynos_drm_mode_config_init(struct drm_device *dev);
-
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_fbdev.c
deleted file mode 100644
index d5586cc..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_fbdev.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/* exynos_drm_fbdev.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm_crtc.h"
-#include "drm_fb_helper.h"
-#include "drm_crtc_helper.h"
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_fb.h"
-#include "exynos_drm_gem.h"
-
-#define MAX_CONNECTOR 4
-#define PREFERRED_BPP 32
-
-#define to_exynos_fbdev(x) container_of(x, struct exynos_drm_fbdev,\
- drm_fb_helper)
-
-struct exynos_drm_fbdev {
- struct drm_fb_helper drm_fb_helper;
- struct exynos_drm_gem_obj *exynos_gem_obj;
-};
-
-static struct fb_ops exynos_drm_fb_ops = {
- .owner = THIS_MODULE,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_setcmap = drm_fb_helper_setcmap,
-};
-
-static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
- struct drm_framebuffer *fb)
-{
- struct fb_info *fbi = helper->fbdev;
- struct drm_device *dev = helper->dev;
- struct exynos_drm_gem_buf *buffer;
- unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
- unsigned long offset;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
- drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
-
- /* RGB formats use only one buffer */
- buffer = exynos_drm_fb_buffer(fb, 0);
- if (!buffer) {
- DRM_LOG_KMS("buffer is null.\n");
- return -EFAULT;
- }
-
- offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
- offset += fbi->var.yoffset * fb->pitches[0];
-
- dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr;
- fbi->screen_base = buffer->kvaddr + offset;
- fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset);
- fbi->screen_size = size;
- fbi->fix.smem_len = size;
-
- return 0;
-}
-
-static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
- struct drm_fb_helper_surface_size *sizes)
-{
- struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_device *dev = helper->dev;
- struct fb_info *fbi;
- struct drm_mode_fb_cmd2 mode_cmd = { 0 };
- struct platform_device *pdev = dev->platformdev;
- unsigned long size;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
- sizes->surface_width, sizes->surface_height,
- sizes->surface_bpp);
-
- mode_cmd.width = sizes->surface_width;
- mode_cmd.height = sizes->surface_height;
- mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3);
- mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
- sizes->surface_depth);
-
- mutex_lock(&dev->struct_mutex);
-
- fbi = framebuffer_alloc(0, &pdev->dev);
- if (!fbi) {
- DRM_ERROR("failed to allocate fb info.\n");
- ret = -ENOMEM;
- goto out;
- }
-
- size = mode_cmd.pitches[0] * mode_cmd.height;
-
- /* 0 means to allocate physically continuous memory */
- exynos_gem_obj = exynos_drm_gem_create(dev, 0, size);
- if (IS_ERR(exynos_gem_obj)) {
- ret = PTR_ERR(exynos_gem_obj);
- goto out;
- }
-
- exynos_fbdev->exynos_gem_obj = exynos_gem_obj;
-
- helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd,
- &exynos_gem_obj->base);
- if (IS_ERR_OR_NULL(helper->fb)) {
- DRM_ERROR("failed to create drm framebuffer.\n");
- ret = PTR_ERR(helper->fb);
- goto out;
- }
-
- helper->fbdev = fbi;
-
- fbi->par = helper;
- fbi->flags = FBINFO_FLAG_DEFAULT;
- fbi->fbops = &exynos_drm_fb_ops;
-
- ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
- if (ret) {
- DRM_ERROR("failed to allocate cmap.\n");
- goto out;
- }
-
- ret = exynos_drm_fbdev_update(helper, helper->fb);
- if (ret < 0) {
- fb_dealloc_cmap(&fbi->cmap);
- goto out;
- }
-
-/*
- * if failed, all resources allocated above would be released by
- * drm_mode_config_cleanup() when drm_load() had been called prior
- * to any specific driver such as fimd or hdmi driver.
- */
-out:
- mutex_unlock(&dev->struct_mutex);
- return ret;
-}
-
-static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
- struct drm_fb_helper_surface_size *sizes)
-{
- int ret = 0;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * with !helper->fb, it means that this funcion is called first time
- * and after that, the helper->fb would be used as clone mode.
- */
- if (!helper->fb) {
- ret = exynos_drm_fbdev_create(helper, sizes);
- if (ret < 0) {
- DRM_ERROR("failed to create fbdev.\n");
- return ret;
- }
-
- /*
- * fb_helper expects a value more than 1 if succeed
- * because register_framebuffer() should be called.
- */
- ret = 1;
- }
-
- return ret;
-}
-
-static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
- .fb_probe = exynos_drm_fbdev_probe,
-};
-
-int exynos_drm_fbdev_init(struct drm_device *dev)
-{
- struct exynos_drm_fbdev *fbdev;
- struct exynos_drm_private *private = dev->dev_private;
- struct drm_fb_helper *helper;
- unsigned int num_crtc;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
- return 0;
-
- fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
- if (!fbdev) {
- DRM_ERROR("failed to allocate drm fbdev.\n");
- return -ENOMEM;
- }
-
- private->fb_helper = helper = &fbdev->drm_fb_helper;
- helper->funcs = &exynos_drm_fb_helper_funcs;
-
- num_crtc = dev->mode_config.num_crtc;
-
- ret = drm_fb_helper_init(dev, helper, num_crtc, MAX_CONNECTOR);
- if (ret < 0) {
- DRM_ERROR("failed to initialize drm fb helper.\n");
- goto err_init;
- }
-
- ret = drm_fb_helper_single_add_all_connectors(helper);
- if (ret < 0) {
- DRM_ERROR("failed to register drm_fb_helper_connector.\n");
- goto err_setup;
-
- }
-
- ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
- if (ret < 0) {
- DRM_ERROR("failed to set up hw configuration.\n");
- goto err_setup;
- }
-
- return 0;
-
-err_setup:
- drm_fb_helper_fini(helper);
-
-err_init:
- private->fb_helper = NULL;
- kfree(fbdev);
-
- return ret;
-}
-
-static void exynos_drm_fbdev_destroy(struct drm_device *dev,
- struct drm_fb_helper *fb_helper)
-{
- struct drm_framebuffer *fb;
-
- /* release drm framebuffer and real buffer */
- if (fb_helper->fb && fb_helper->fb->funcs) {
- fb = fb_helper->fb;
- if (fb && fb->funcs->destroy)
- fb->funcs->destroy(fb);
- }
-
- /* release linux framebuffer */
- if (fb_helper->fbdev) {
- struct fb_info *info;
- int ret;
-
- info = fb_helper->fbdev;
- ret = unregister_framebuffer(info);
- if (ret < 0)
- DRM_DEBUG_KMS("failed unregister_framebuffer()\n");
-
- if (info->cmap.len)
- fb_dealloc_cmap(&info->cmap);
-
- framebuffer_release(info);
- }
-
- drm_fb_helper_fini(fb_helper);
-}
-
-void exynos_drm_fbdev_fini(struct drm_device *dev)
-{
- struct exynos_drm_private *private = dev->dev_private;
- struct exynos_drm_fbdev *fbdev;
-
- if (!private || !private->fb_helper)
- return;
-
- fbdev = to_exynos_fbdev(private->fb_helper);
-
- if (fbdev->exynos_gem_obj)
- exynos_drm_gem_destroy(fbdev->exynos_gem_obj);
-
- exynos_drm_fbdev_destroy(dev, private->fb_helper);
- kfree(fbdev);
- private->fb_helper = NULL;
-}
-
-void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
-{
- struct exynos_drm_private *private = dev->dev_private;
-
- if (!private || !private->fb_helper)
- return;
-
- drm_fb_helper_restore_fbdev_mode(private->fb_helper);
-}
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_fbdev.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_fbdev.h
deleted file mode 100644
index ccfce8a..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_fbdev.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_FBDEV_H_
-#define _EXYNOS_DRM_FBDEV_H_
-
-int exynos_drm_fbdev_init(struct drm_device *dev);
-int exynos_drm_fbdev_reinit(struct drm_device *dev);
-void exynos_drm_fbdev_fini(struct drm_device *dev);
-void exynos_drm_fbdev_restore_mode(struct drm_device *dev);
-
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_fimd.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_fimd.c
deleted file mode 100644
index 6ec2a61..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_fimd.c
+++ /dev/null
@@ -1,1700 +0,0 @@
-/* exynos_drm_fimd.c
- *
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- * Joonyoung Shim <jy0922.shim@samsung.com>
- * Inki Dae <inki.dae@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-#include "drmP.h"
-#include "drm_backlight.h"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/pm_runtime.h>
-#include <linux/cma.h>
-
-#include <drm/exynos_drm.h>
-#include <plat/regs-fb-v4.h>
-
-#include <plat/fimd_lite_ext.h>
-
-#include <mach/map.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_fbdev.h"
-#include "exynos_drm_crtc.h"
-
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
-#include <linux/devfreq/exynos4_display.h>
-#endif
-
-#ifdef CONFIG_MACH_SLP_NAPLES
-#define VIDCON0_DSI_DISABLE (0 << 30)
-#define VIDCON0_DSI_ENABLE (1 << 30)
-
-/* I80/RGB Trigger control */
-#define TRIGCON (0x01A4)
-/* I80 interface control 0 for main LDI */
-#define I80IFCONA0 (0x01B0)
-#define I80IFCONA1 (0x01B4)
-#define I80IFCONB0 (0x01B8)
-#define I80IFCONB1 (0x01B8)
-
-/* I80IFCONA0 and I80IFCONA1 */
-#define LCD_CS_SETUP(x) (((x) & 0xf) << 16)
-#define LCD_WR_SETUP(x) (((x) & 0xf) << 12)
-#define LCD_WR_ACT(x) (((x) & 0xf) << 8)
-#define LCD_WR_HOLD(x) (((x) & 0xf) << 4)
-#define RSPOL_LOW (0 << 2)
-#define RSPOL_HIGH (1 << 2)
-#define I80IFEN_DISABLE (0 << 0)
-#define I80IFEN_ENABLE (1 << 0)
-
-enum s3cfb_cpu_auto_cmd_rate {
- DISABLE_AUTO_FRM,
- PER_TWO_FRM,
- PER_FOUR_FRM,
- PER_SIX_FRM,
- PER_EIGHT_FRM,
- PER_TEN_FRM,
- PER_TWELVE_FRM,
- PER_FOURTEEN_FRM,
- PER_SIXTEEN_FRM,
- PER_EIGHTEEN_FRM,
- PER_TWENTY_FRM,
- PER_TWENTY_TWO_FRM,
- PER_TWENTY_FOUR_FRM,
- PER_TWENTY_SIX_FRM,
- PER_TWENTY_EIGHT_FRM,
- PER_THIRTY_FRM,
-};
-#endif
-#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
-#include <plat/fimc.h>
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
-#include <plat/pd.h>
-#include <linux/pm_qos_params.h>
-#endif
-#define FIMD_GET_LCD_WIDTH _IOR('F', 302, int)
-#define FIMD_GET_LCD_HEIGHT _IOR('F', 303, int)
-#define FIMD_SET_WRITEBACK _IOW('F', 304, u32)
-#endif
-
-/*
- * FIMD is stand for Fully Interactive Mobile Display and
- * as a display controller, it transfers contents drawn on memory
- * to a LCD Panel through Display Interfaces such as RGB or
- * CPU Interface.
- */
-
-/* position control register for hardware window 0, 2 ~ 4.*/
-#define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16)
-#define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16)
-/* size control register for hardware window 0. */
-#define VIDOSD_C_SIZE_W0 (VIDOSD_BASE + 0x08)
-/* alpha control register for hardware window 1 ~ 4. */
-#define VIDOSD_C(win) (VIDOSD_BASE + 0x18 + (win) * 16)
-/* size control register for hardware window 1 ~ 4. */
-#define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16)
-
-#define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8)
-#define VIDWx_BUF_END(win, buf) (VIDW_BUF_END(buf) + (win) * 8)
-#define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4)
-
-/* color key control register for hardware window 1 ~ 4. */
-#define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + (x * 8))
-/* color key value register for hardware window 1 ~ 4. */
-#define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + (x * 8))
-
-/* FIMD has totally five hardware windows. */
-#define WINDOWS_NR 5
-
-#define get_fimd_context(dev) platform_get_drvdata(to_platform_device(dev))
-
-static struct s5p_fimd_ext_device *fimd_lite_dev, *mdnie;
-static struct s5p_fimd_dynamic_refresh *fimd_refresh;
-
-struct fimd_notifier_block {
- struct list_head list;
- void *data;
- int (*client_notifier)(unsigned int val, void *data);
-};
-
-static LIST_HEAD(fimd_notifier_list);
-static DEFINE_MUTEX(fimd_notifier_lock);
-
-struct fimd_win_data {
- unsigned int offset_x;
- unsigned int offset_y;
- unsigned int ovl_width;
- unsigned int ovl_height;
- unsigned int fb_width;
- unsigned int fb_height;
- unsigned int bpp;
- dma_addr_t dma_addr;
- void __iomem *vaddr;
- unsigned int buf_offsize;
- unsigned int line_size; /* bytes */
- bool enabled;
-};
-
-struct fimd_context {
- struct exynos_drm_subdrv subdrv;
- int irq;
- struct drm_crtc *crtc;
- struct clk *bus_clk;
- struct clk *lcd_clk;
- struct resource *regs_res;
- void __iomem *regs;
- struct fimd_win_data win_data[WINDOWS_NR];
- unsigned int clkdiv;
- unsigned int default_win;
- unsigned long irq_flags;
- u32 vidcon0;
- u32 vidcon1;
- bool suspended;
- struct mutex lock;
-
- struct exynos_drm_panel_info *panel;
- unsigned int high_freq;
- unsigned int dynamic_refresh;
- struct notifier_block nb_exynos_display;
-
- struct work_struct work;
- bool errata;
-#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
- struct notifier_block nb_ctrl;
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- struct pm_qos_request_list pm_qos;
-#endif
-#endif
-};
-#ifdef CONFIG_MACH_SLP_NAPLES
-struct fimd_context *ctx_global;
-#endif
-
-static bool fimd_display_is_connected(struct device *dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO. */
-
- return true;
-}
-
-static void *fimd_get_panel(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return ctx->panel;
-}
-
-static int fimd_check_timing(struct device *dev, void *timing)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO. */
-
- return 0;
-}
-
-static int fimd_display_power_on(struct device *dev, int mode)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO */
-
- drm_bl_dpms(mode);
-
- return 0;
-}
-
-static struct exynos_drm_display_ops fimd_display_ops = {
- .type = EXYNOS_DISPLAY_TYPE_LCD,
- .is_connected = fimd_display_is_connected,
- .get_panel = fimd_get_panel,
- .check_timing = fimd_check_timing,
- .power_on = fimd_display_power_on,
-};
-
-static void exynos_drm_mdnie_mode_stop(struct fimd_context *ctx)
-{
- struct s5p_fimd_ext_driver *fimd_lite_drv;
- u32 cfg;
-
- fimd_lite_drv = to_fimd_ext_driver(fimd_lite_dev->dev.driver);
-
- /* set dualrgb register to mDNIe mode. */
- cfg = readl(ctx->regs + DUALRGB);
- cfg &= ~(0x3 << 0);
- writel(cfg, ctx->regs + DUALRGB);
- msleep(20);
-
- /* change display path. */
- cfg = readl(S3C_VA_SYS + 0x210);
- cfg |= 1 << 1;
- writel(cfg, S3C_VA_SYS + 0x210);
-
- if (fimd_lite_drv->stop)
- fimd_lite_drv->stop(fimd_lite_dev);
-
- if (fimd_lite_drv->setup)
- fimd_lite_drv->setup(fimd_lite_dev, 0);
-
- /* clock off */
- if (fimd_lite_drv->power_off)
- fimd_lite_drv->power_off(fimd_lite_dev);
-
- fimd_lite_dev->enabled = false;
-}
-
-static void exynos_drm_set_mdnie_mode(struct fimd_context *ctx)
-{
- u32 cfg;
-
- /* change display path. */
- cfg = readl(S3C_VA_SYS + 0x210);
- /* MIE_LBLK0 is mDNIe. */
- cfg |= 1 << 0;
- /* FIMDBYPASS_LBLK0 is MIE/mDNIe. */
- cfg &= ~(1 << 1);
- writel(cfg, S3C_VA_SYS + 0x210);
-
- /* all polarity values should be 0 for mDNIe. */
- cfg = readl(ctx->regs + VIDCON1);
- cfg &= ~(VIDCON1_INV_VCLK | VIDCON1_INV_HSYNC |
- VIDCON1_INV_VSYNC | VIDCON1_INV_VDEN |
- VIDCON1_VCLK_MASK);
-
- writel(cfg, ctx->regs + VIDCON1);
-
- /* set dualrgb register to mDNIe mode. */
- cfg = readl(ctx->regs + DUALRGB);
- cfg &= ~(0x3 << 0);
- cfg |= 0x3 << 0;
- writel(cfg, ctx->regs + DUALRGB);
-}
-
-static int exynos_drm_change_to_mdnie(struct fimd_context *ctx)
-{
- u32 cfg;
- struct s5p_fimd_ext_driver *mdnie_drv, *fimd_lite_drv;
-
- mdnie_drv = to_fimd_ext_driver(mdnie->dev.driver);
- fimd_lite_drv = to_fimd_ext_driver(fimd_lite_dev->dev.driver);
-
- /**
- * path change sequence for mDNIe.
- *
- * 1. FIMD-LITE DMA stop.
- * 2. FIMD DMA stop.
- * 3. change DISPLAY_CONTROL and DUALRGB registers to mDNIe mode.
- * 4. change FIMD VCLKFREE to freerun mode.
- * 5. initialize mDNIe module.
- * 6. initialize FIMD-LITE module.
- * 7. FIMD-LITE logic start.
- * 8. FIMD-LITE DMA start.
- * 9. FIMD DMA start.
- *
- * ps. FIMD polarity values should be 0.
- * lcd polarity values should be set to FIMD-LITE.
- * FIMD and FIMD-LITE DMA should be started at same time.
- */
- /* set fimd to mDNIe mode.(WB/mDNIe) */
- exynos_drm_set_mdnie_mode(ctx);
-
- /* enable FIMD-LITE. clk */
- if (fimd_lite_drv && fimd_lite_drv->power_on)
- fimd_lite_drv->power_on(fimd_lite_dev);
-
- /* setup mDNIe. */
- if (mdnie_drv)
- mdnie_drv->setup(mdnie, 1);
-
- /* setup FIMD-LITE. */
- if (fimd_lite_drv)
- fimd_lite_drv->setup(fimd_lite_dev, 1);
-
- cfg = readl(ctx->regs + VIDCON0);
- cfg |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- writel(cfg, ctx->regs + VIDCON0);
-
- if (fimd_lite_drv->start)
- fimd_lite_drv->start(fimd_lite_dev);
- return 0;
-}
-
-static void fimd_dpms(struct device *subdrv_dev, int mode)
-{
- struct fimd_context *ctx = get_fimd_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
-
- mutex_lock(&ctx->lock);
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- /*
- * enable fimd hardware only if suspended status.
- *
- * P.S. fimd_dpms function would be called at booting time so
- * clk_enable could be called double time.
- */
- if (ctx->suspended)
- pm_runtime_get_sync(subdrv_dev);
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- if (!ctx->suspended)
- pm_runtime_put_sync(subdrv_dev);
- break;
- default:
- DRM_DEBUG_KMS("unspecified mode %d\n", mode);
- break;
- }
-
- mutex_unlock(&ctx->lock);
-}
-
-static void fimd_apply(struct device *subdrv_dev)
-{
- struct fimd_context *ctx = get_fimd_context(subdrv_dev);
- struct exynos_drm_manager *mgr = ctx->subdrv.manager;
- struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
- struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
- struct fimd_win_data *win_data;
- int i;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- for (i = 0; i < WINDOWS_NR; i++) {
- win_data = &ctx->win_data[i];
- if (win_data->enabled && (ovl_ops && ovl_ops->commit))
- ovl_ops->commit(subdrv_dev, i);
- }
-
- if (mgr_ops && mgr_ops->commit)
- mgr_ops->commit(subdrv_dev);
-}
-
-#ifdef CONFIG_MACH_SLP_NAPLES
-void _fimd_set_auto_cmd_rate(struct fimd_context *ctx, unsigned char cmd_rate)
-{
- unsigned int cmd_rate_val;
- unsigned int i80_if_con_reg_val;
-
- cmd_rate_val = (cmd_rate == DISABLE_AUTO_FRM) ? (0x0 << 0) :
- (cmd_rate == PER_TWO_FRM) ? (0x1 << 0) :
- (cmd_rate == PER_FOUR_FRM) ? (0x2 << 0) :
- (cmd_rate == PER_SIX_FRM) ? (0x3 << 0) :
- (cmd_rate == PER_EIGHT_FRM) ? (0x4 << 0) :
- (cmd_rate == PER_TEN_FRM) ? (0x5 << 0) :
- (cmd_rate == PER_TWELVE_FRM) ? (0x6 << 0) :
- (cmd_rate == PER_FOURTEEN_FRM) ? (0x7 << 0) :
- (cmd_rate == PER_SIXTEEN_FRM) ? (0x8 << 0) :
- (cmd_rate == PER_EIGHTEEN_FRM) ? (0x9 << 0) :
- (cmd_rate == PER_TWENTY_FRM) ? (0xa << 0) :
- (cmd_rate == PER_TWENTY_TWO_FRM) ? (0xb << 0) :
- (cmd_rate == PER_TWENTY_FOUR_FRM) ? (0xc << 0) :
- (cmd_rate == PER_TWENTY_SIX_FRM) ? (0xd << 0) :
- (cmd_rate == PER_TWENTY_EIGHT_FRM) ? (0xe << 0) : (0xf << 0);
-
- i80_if_con_reg_val = readl(ctx->regs + I80IFCONB0);
- i80_if_con_reg_val &= ~(0xf << 0);
- i80_if_con_reg_val |= cmd_rate_val;
- writel(i80_if_con_reg_val, ctx->regs + I80IFCONB0);
-}
-#endif
-static void fimd_commit(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
- u32 val;
-
- if (ctx->suspended)
- return;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
-#ifdef CONFIG_MACH_SLP_NAPLES
- /* setup horizontal and vertical display size. */
- val = VIDTCON2_LINEVAL(timing->yres - 1) |
- VIDTCON2_HOZVAL(timing->xres - 1);
- writel(val, ctx->regs + VIDTCON2);
-
- /* cpu_interface_timing */
- val = readl(ctx->regs + I80IFCONA0);
- val = LCD_CS_SETUP(0) |
- LCD_WR_SETUP(0) |
- LCD_WR_ACT(1) |
- LCD_WR_HOLD(0) |
- RSPOL_LOW | /* in case of LCD MIPI module */
- I80IFEN_ENABLE;
- writel(val, ctx->regs + I80IFCONA0);
-
- _fimd_set_auto_cmd_rate(ctx, DISABLE_AUTO_FRM);
-
- /* setup clock source, clock divider, enable dma. */
- val = ctx->vidcon0;
- val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
-
- if (ctx->clkdiv > 1)
- val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1)
- | VIDCON0_CLKDIR;
- else
- val &= ~VIDCON0_CLKDIR; /* 1:1 clock */
-
- /*
- * fields of register with prefix '_F' would be updated
- * at vsync(same as dma start)
- */
- val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- writel(val, ctx->regs + VIDCON0);
-
- /*
- * Workaround: After power domain is turned off
- * then when it is turned on, this needs.
- */
- val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F);
- writel(val, ctx->regs + VIDCON0);
-
- val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- writel(val, ctx->regs + VIDCON0);
-#else
- /* setup polarity values from machine code. */
- writel(ctx->vidcon1, ctx->regs + VIDCON1);
-
- /* setup vertical timing values. */
- val = VIDTCON0_VBPD(timing->upper_margin - 1) |
- VIDTCON0_VFPD(timing->lower_margin - 1) |
- VIDTCON0_VSPW(timing->vsync_len - 1);
- writel(val, ctx->regs + VIDTCON0);
-
- /* setup horizontal timing values. */
- val = VIDTCON1_HBPD(timing->left_margin - 1) |
- VIDTCON1_HFPD(timing->right_margin - 1) |
- VIDTCON1_HSPW(timing->hsync_len - 1);
- writel(val, ctx->regs + VIDTCON1);
-
- /* setup horizontal and vertical display size. */
- val = VIDTCON2_LINEVAL(timing->yres - 1) |
- VIDTCON2_HOZVAL(timing->xres - 1);
- writel(val, ctx->regs + VIDTCON2);
-
- /* setup clock source, clock divider, enable dma. */
- val = ctx->vidcon0;
- val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
-
- if (ctx->clkdiv > 1)
- val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
- else
- val &= ~VIDCON0_CLKDIR; /* 1:1 clock */
-
- /*
- * fields of register with prefix '_F' would be updated
- * at vsync(same as dma start)
- */
- val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- writel(val, ctx->regs + VIDCON0);
-
- /*
- * fix fimd errata with mDNIe.
- *
- * this code fixes a issue that mDNIe unfunctions properly
- * when fimd power off goes to on. this issue is because dma
- * is enabled two times with setcrtc call once a process is
- * ternimated(at this thime, fimd goes to on from off for back
- * to console fb) so this condition would avoid the situation.
- */
- if (!ctx->errata) {
- /*
- * Workaround: After power domain is turned off then
- * when it is turned on, this needs.
- */
- val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F);
- writel(val, ctx->regs + VIDCON0);
-
- val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- writel(val, ctx->regs + VIDCON0);
-
- ctx->errata = true;
- }
-#endif
-}
-
-static int fimd_enable_vblank(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- u32 val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return -EPERM;
-
- if (!test_and_set_bit(0, &ctx->irq_flags)) {
- val = readl(ctx->regs + VIDINTCON0);
-
- val |= VIDINTCON0_INT_ENABLE;
- val |= VIDINTCON0_INT_FRAME;
-
- val &= ~VIDINTCON0_FRAMESEL0_MASK;
- val |= VIDINTCON0_FRAMESEL0_VSYNC;
- val &= ~VIDINTCON0_FRAMESEL1_MASK;
- val |= VIDINTCON0_FRAMESEL1_NONE;
-
- writel(val, ctx->regs + VIDINTCON0);
- }
-
- return 0;
-}
-
-static void fimd_disable_vblank(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- u32 val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return;
-
- if (test_and_clear_bit(0, &ctx->irq_flags)) {
- val = readl(ctx->regs + VIDINTCON0);
-
- val &= ~VIDINTCON0_INT_FRAME;
- val &= ~VIDINTCON0_INT_ENABLE;
-
- writel(val, ctx->regs + VIDINTCON0);
- }
-}
-
-static struct exynos_drm_manager_ops fimd_manager_ops = {
- .dpms = fimd_dpms,
- .apply = fimd_apply,
- .commit = fimd_commit,
- .enable_vblank = fimd_enable_vblank,
- .disable_vblank = fimd_disable_vblank,
-};
-
-static void fimd_win_mode_set(struct device *dev,
- struct exynos_drm_overlay *overlay)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct fimd_win_data *win_data;
- int win;
- unsigned long offset;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!overlay) {
- dev_err(dev, "overlay is NULL\n");
- return;
- }
-
- win = overlay->zpos;
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- offset = overlay->fb_x * (overlay->bpp >> 3);
- offset += overlay->fb_y * overlay->pitch;
-
- DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
-
- win_data = &ctx->win_data[win];
-
- win_data->offset_x = overlay->crtc_x;
- win_data->offset_y = overlay->crtc_y;
- win_data->ovl_width = overlay->crtc_width;
- win_data->ovl_height = overlay->crtc_height;
- win_data->fb_width = overlay->fb_width;
- win_data->fb_height = overlay->fb_height;
- win_data->dma_addr = overlay->dma_addr[0] + offset;
- win_data->vaddr = overlay->vaddr[0] + offset;
- win_data->bpp = overlay->bpp;
- win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
- (overlay->bpp >> 3);
- win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
-
- DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
- win_data->offset_x, win_data->offset_y);
- DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
- win_data->ovl_width, win_data->ovl_height);
- DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
- (unsigned long)win_data->dma_addr,
- (unsigned long)win_data->vaddr);
- DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
- overlay->fb_width, overlay->crtc_width);
-}
-
-static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct fimd_win_data *win_data = &ctx->win_data[win];
- unsigned long val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- val = WINCONx_ENWIN;
-
- switch (win_data->bpp) {
- case 1:
- val |= WINCON0_BPPMODE_1BPP;
- val |= WINCONx_BITSWP;
- val |= WINCONx_BURSTLEN_4WORD;
- break;
- case 2:
- val |= WINCON0_BPPMODE_2BPP;
- val |= WINCONx_BITSWP;
- val |= WINCONx_BURSTLEN_8WORD;
- break;
- case 4:
- val |= WINCON0_BPPMODE_4BPP;
- val |= WINCONx_BITSWP;
- val |= WINCONx_BURSTLEN_8WORD;
- break;
- case 8:
- val |= WINCON0_BPPMODE_8BPP_PALETTE;
- val |= WINCONx_BURSTLEN_8WORD;
- val |= WINCONx_BYTSWP;
- break;
- case 16:
- val |= WINCON0_BPPMODE_16BPP_565;
- val |= WINCONx_HAWSWP;
- val |= WINCONx_BURSTLEN_16WORD;
- break;
- case 24:
- val |= WINCON0_BPPMODE_24BPP_888;
- val |= WINCONx_WSWP;
- val |= WINCONx_BURSTLEN_16WORD;
- break;
- case 32:
- val |= WINCON1_BPPMODE_28BPP_A4888
- | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
- val |= WINCONx_WSWP;
- val |= WINCONx_BURSTLEN_16WORD;
- break;
- default:
- DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
-
- val |= WINCON0_BPPMODE_24BPP_888;
- val |= WINCONx_WSWP;
- val |= WINCONx_BURSTLEN_16WORD;
- break;
- }
-
- DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
-
- writel(val, ctx->regs + WINCON(win));
-}
-
-static void fimd_win_set_colkey(struct device *dev, unsigned int win)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- unsigned int keycon0 = 0, keycon1 = 0;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
- WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
-
- keycon1 = WxKEYCON1_COLVAL(0xffffffff);
-
- writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
- writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
-}
-
-static void fimd_win_commit(struct device *dev, int zpos)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct fimd_win_data *win_data;
- int win = zpos;
- unsigned long val, alpha, size;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return;
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- win_data = &ctx->win_data[win];
-
- /*
- * SHADOWCON register is used for enabling timing.
- *
- * for example, once only width value of a register is set,
- * if the dma is started then fimd hardware could malfunction so
- * with protect window setting, the register fields with prefix '_F'
- * wouldn't be updated at vsync also but updated once unprotect window
- * is set.
- */
-
- /* protect windows */
- val = readl(ctx->regs + SHADOWCON);
- val |= SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-
- /* buffer start address */
- val = (unsigned long)win_data->dma_addr;
- writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
-
- /* buffer end address */
- size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
- val = (unsigned long)(win_data->dma_addr + size);
- writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
-
- DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
- (unsigned long)win_data->dma_addr, val, size);
- DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
- win_data->ovl_width, win_data->ovl_height);
-
- /* buffer size */
- val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
- VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size);
- writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
-
- /* OSD position */
- val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
- VIDOSDxA_TOPLEFT_Y(win_data->offset_y);
- writel(val, ctx->regs + VIDOSD_A(win));
-
- val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x +
- win_data->ovl_width - 1) |
- VIDOSDxB_BOTRIGHT_Y(win_data->offset_y +
- win_data->ovl_height - 1);
- writel(val, ctx->regs + VIDOSD_B(win));
-
- DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
- win_data->offset_x, win_data->offset_y,
- win_data->offset_x + win_data->ovl_width - 1,
- win_data->offset_y + win_data->ovl_height - 1);
-
- /* hardware window 0 doesn't support alpha channel. */
- if (win != 0) {
- /* OSD alpha */
- alpha = VIDISD14C_ALPHA1_R(0xf) |
- VIDISD14C_ALPHA1_G(0xf) |
- VIDISD14C_ALPHA1_B(0xf);
-
- writel(alpha, ctx->regs + VIDOSD_C(win));
- }
-
- /* OSD size */
- if (win != 3 && win != 4) {
- u32 offset = VIDOSD_D(win);
- if (win == 0)
- offset = VIDOSD_C_SIZE_W0;
- val = win_data->ovl_width * win_data->ovl_height;
- writel(val, ctx->regs + offset);
-
- DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
- }
-
- fimd_win_set_pixfmt(dev, win);
-
- /* hardware window 0 doesn't support color key. */
- if (win != 0)
- fimd_win_set_colkey(dev, win);
-
- /* wincon */
- val = readl(ctx->regs + WINCON(win));
- val |= WINCONx_ENWIN;
- writel(val, ctx->regs + WINCON(win));
-
- /* Enable DMA channel and unprotect windows */
- val = readl(ctx->regs + SHADOWCON);
- val |= SHADOWCON_CHx_ENABLE(win);
- val &= ~SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-
- win_data->enabled = true;
-}
-
-static void fimd_win_disable(struct device *dev, int zpos)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct fimd_win_data *win_data;
- int win = zpos;
- u32 val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- win_data = &ctx->win_data[win];
-
- /* protect windows */
- val = readl(ctx->regs + SHADOWCON);
- val |= SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-
- /* wincon */
- val = readl(ctx->regs + WINCON(win));
- val &= ~WINCONx_ENWIN;
- writel(val, ctx->regs + WINCON(win));
-
- /* unprotect windows */
- val = readl(ctx->regs + SHADOWCON);
- val &= ~SHADOWCON_CHx_ENABLE(win);
- val &= ~SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-
- win_data->enabled = false;
-}
-
-static struct exynos_drm_overlay_ops fimd_overlay_ops = {
- .mode_set = fimd_win_mode_set,
- .commit = fimd_win_commit,
- .disable = fimd_win_disable,
-};
-
-static struct exynos_drm_manager fimd_manager = {
- .pipe = -1,
- .ops = &fimd_manager_ops,
- .overlay_ops = &fimd_overlay_ops,
- .display_ops = &fimd_display_ops,
-};
-
-static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
-{
- struct exynos_drm_private *dev_priv = drm_dev->dev_private;
- struct drm_pending_vblank_event *e, *t;
- struct timeval now;
- unsigned long flags;
- bool is_checked = false;
-
- spin_lock_irqsave(&drm_dev->event_lock, flags);
-
- list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
- base.link) {
- /* if event's pipe isn't same as crtc then ignore it. */
- if (crtc != e->pipe)
- continue;
-
- is_checked = true;
-
- do_gettimeofday(&now);
- e->event.sequence = 0;
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
-
- list_move_tail(&e->base.link, &e->base.file_priv->event_list);
- wake_up_interruptible(&e->base.file_priv->event_wait);
- }
-
- if (is_checked) {
- /*
- * call drm_vblank_put only in case that drm_vblank_get was
- * called.
- */
- if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
- drm_vblank_put(drm_dev, crtc);
-
- /*
- * don't off vblank if vblank_disable_allowed is 1,
- * because vblank would be off by timer handler.
- */
- if (!drm_dev->vblank_disable_allowed)
- drm_vblank_off(drm_dev, crtc);
- }
-
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-}
-
-static void exynos_fimd_schedule_work(struct work_struct *work)
-{
- struct fimd_context *ctx = container_of(work, struct fimd_context,
- work);
- u32 ret;
-
- /* Change mdnie mode after irq handler */
- if (mdnie && fimd_lite_dev) {
- if (!fimd_lite_dev->enabled) {
- while (1) {
- ret = (__raw_readl(ctx->regs + VIDCON1)) &
- VIDCON1_VSTATUS_MASK;
- if (ret == VIDCON1_VSTATUS_BACKPORCH) {
- exynos_drm_change_to_mdnie(ctx);
- fimd_lite_dev->enabled = true;
- break;
- }
- }
- }
- }
-
-}
-
-#ifdef CONFIG_MACH_SLP_NAPLES
-void fimd_set_trigger(void)
-{
- u32 reg = 0;
- struct exynos_drm_subdrv *subdrv = &ctx_global->subdrv;
- struct drm_device *drm_dev = subdrv->drm_dev;
- struct exynos_drm_manager *manager = subdrv->manager;
- u32 val;
-
- val = readl(ctx_global->regs + VIDINTCON1);
-
- if (val & VIDINTCON1_INT_FRAME)
- /* VSYNC interrupt */
- writel(VIDINTCON1_INT_FRAME, ctx_global->regs + VIDINTCON1);
-
- /* check the crtc is detached already from encoder */
- if (manager->pipe < 0)
- return;
-
- drm_handle_vblank(drm_dev, manager->pipe);
- fimd_finish_pageflip(drm_dev, manager->pipe);
-
- schedule_work(&ctx_global->work);
-
- reg = readl(ctx_global->regs + TRIGCON);
-
- reg |= 1 << 0 | 1 << 1;
-
- writel(reg, ctx_global->regs + TRIGCON);
-}
-#endif
-static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
-{
- struct fimd_context *ctx = (struct fimd_context *)dev_id;
- struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct drm_device *drm_dev = subdrv->drm_dev;
- struct exynos_drm_manager *manager = subdrv->manager;
- u32 val;
-
- val = readl(ctx->regs + VIDINTCON1);
-
- if (val & VIDINTCON1_INT_FRAME)
- /* VSYNC interrupt */
- writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
-
- /* check the crtc is detached already from encoder */
- if (manager->pipe < 0)
- goto out;
-
- drm_handle_vblank(drm_dev, manager->pipe);
- fimd_finish_pageflip(drm_dev, manager->pipe);
-
- schedule_work(&ctx->work);
-
-out:
- return IRQ_HANDLED;
-}
-
-static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * enable drm irq mode.
- * - with irq_enabled = 1, we can use the vblank feature.
- *
- * P.S. note that we wouldn't use drm irq handler but
- * just specific driver own one instead because
- * drm framework supports only one irq handler.
- */
- drm_dev->irq_enabled = 1;
-
- /*
- * with vblank_disable_allowed = 1, vblank interrupt will be disabled
- * by drm timer once a current process gives up ownership of
- * vblank event.(after drm_vblank_put function is called)
- */
- drm_dev->vblank_disable_allowed = 1;
-
- return 0;
-}
-
-static void fimd_subdrv_remove(struct drm_device *drm_dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO. */
-}
-
-static int fimd_calc_clkdiv(struct fimd_context *ctx,
- struct fb_videomode *timing)
-{
- unsigned long clk = clk_get_rate(ctx->lcd_clk);
- u32 retrace;
- u32 clkdiv;
- u32 best_framerate = 0;
- u32 framerate;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
-#ifdef CONFIG_MACH_SLP_NAPLES
- retrace = timing->xres * timing->yres * 2;
-#else
- retrace = timing->left_margin + timing->hsync_len +
- timing->right_margin + timing->xres;
- retrace *= timing->upper_margin + timing->vsync_len +
- timing->lower_margin + timing->yres;
-#endif
-
- /* default framerate is 60Hz */
- if (!timing->refresh)
- timing->refresh = 60;
-
- clk /= retrace;
-
- for (clkdiv = 1; clkdiv < 0x100; clkdiv++) {
- int tmp;
-
- /* get best framerate */
- framerate = clk / clkdiv;
- tmp = timing->refresh - framerate;
- if (tmp < 0) {
- best_framerate = framerate;
- continue;
- } else {
- if (!best_framerate)
- best_framerate = framerate;
- else if (tmp < (best_framerate - framerate))
- best_framerate = framerate;
- break;
- }
- }
-
- return clkdiv;
-}
-
-static void fimd_clear_win(struct fimd_context *ctx, int win)
-{
- u32 val;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- writel(0, ctx->regs + WINCON(win));
- writel(0, ctx->regs + VIDOSD_A(win));
- writel(0, ctx->regs + VIDOSD_B(win));
- writel(0, ctx->regs + VIDOSD_C(win));
-
- if (win == 1 || win == 2)
- writel(0, ctx->regs + VIDOSD_D(win));
-
- val = readl(ctx->regs + SHADOWCON);
- val &= ~SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-}
-
-int fimd_register_client(int (*client_notifier)(unsigned int val, void *data),
- void *data)
-{
- struct fimd_notifier_block *fimd_block;
-
- fimd_block = kzalloc(sizeof(*fimd_block), GFP_KERNEL);
- if (!fimd_block) {
- printk(KERN_ERR "failed to allocate fimd_notifier_block\n");
- return -ENOMEM;
- }
-
- fimd_block->client_notifier = client_notifier;
- fimd_block->data = data;
-
- mutex_lock(&fimd_notifier_lock);
- list_add_tail(&fimd_block->list, &fimd_notifier_list);
- mutex_unlock(&fimd_notifier_lock);
-
- return 0;
-}
-EXPORT_SYMBOL(fimd_register_client);
-
-void fimd_unregister_client(int (*client_notifier)(unsigned int val,
- void *data))
-{
- struct fimd_notifier_block *fimd_block;
-
- mutex_lock(&fimd_notifier_lock);
- list_for_each_entry(fimd_block, &fimd_notifier_list, list) {
- if (!fimd_block)
- continue;
-
- if (fimd_block->client_notifier == client_notifier) {
- list_del(&fimd_block->list);
- kfree(fimd_block);
- fimd_block = NULL;
- break;
- }
- }
- mutex_unlock(&fimd_notifier_lock);
-}
-EXPORT_SYMBOL(fimd_unregister_client);
-
-static int fimd_notifier_call_chain(void)
-{
- struct fimd_notifier_block *fimd_block;
-
- mutex_lock(&fimd_notifier_lock);
- list_for_each_entry(fimd_block, &fimd_notifier_list, list) {
- if (fimd_block && fimd_block->client_notifier)
- fimd_block->client_notifier(0, fimd_block->data);
- }
- mutex_unlock(&fimd_notifier_lock);
-
- return 0;
-}
-
-static int fimd_power_on(struct fimd_context *ctx, bool enable)
-{
- struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct device *dev = subdrv->dev;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (enable != false && enable != true)
- return -EINVAL;
-
- if (enable) {
- int ret;
-
- /* fimd power should be off to clear mipi-dsi fifo. */
- fimd_notifier_call_chain();
-
- ret = clk_enable(ctx->bus_clk);
- if (ret < 0)
- return ret;
-
- ret = clk_enable(ctx->lcd_clk);
- if (ret < 0) {
- clk_disable(ctx->bus_clk);
- return ret;
- }
-
- ctx->suspended = false;
-
- /* if vblank was enabled status, enable it again. */
- if (test_and_clear_bit(0, &ctx->irq_flags))
- fimd_enable_vblank(dev);
-
- fimd_apply(dev);
- } else {
- if (fimd_lite_dev)
- exynos_drm_mdnie_mode_stop(ctx);
-
- clk_disable(ctx->lcd_clk);
- clk_disable(ctx->bus_clk);
-
- ctx->suspended = true;
- ctx->errata = false;
- }
-
- return 0;
-}
-
-static void exynos_drm_change_clock(struct fimd_context *ctx)
-{
- unsigned int cfg = 0;
- struct s5p_fimd_ext_driver *fimd_lite_drv;
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
-
- fimd_lite_drv = to_fimd_ext_driver(fimd_lite_dev->dev.driver);
-
- if (!ctx->dynamic_refresh) {
- timing->refresh = 60;
- ctx->clkdiv = fimd_calc_clkdiv(ctx, timing);
-#ifdef CONFIG_LCD_S6E8AA0
- /* workaround: To apply dynamic refresh rate */
- s6e8aa0_panel_cond(1);
-#endif
- if (fimd_lite_dev && fimd_lite_dev->enabled) {
- fimd_refresh->clkdiv = ctx->clkdiv;
- fimd_lite_drv->change_clock(fimd_refresh,
- fimd_lite_dev);
- } else {
- cfg = readl(ctx->regs + VIDCON0);
- cfg &= ~VIDCON0_CLKVAL_F(0xFF);
- cfg |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1);
- writel(cfg, ctx->regs + VIDCON0);
- }
- } else {
- ctx->clkdiv = fimd_calc_clkdiv(ctx, timing);
-#ifdef CONFIG_LCD_S6E8AA0
- /* workaround: To apply dynamic refresh rate */
- s6e8aa0_panel_cond(ctx->high_freq);
-#endif
- if (fimd_lite_dev && fimd_lite_dev->enabled) {
- fimd_refresh->clkdiv = ctx->clkdiv;
- fimd_lite_drv->change_clock(fimd_refresh,
- fimd_lite_dev);
- } else {
- cfg = readl(ctx->regs + VIDCON0);
- cfg &= ~VIDCON0_CLKVAL_F(0xFF);
- cfg |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1);
- writel(cfg, ctx->regs + VIDCON0);
- }
- }
-}
-
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
-static int exynos_display_notifier_callback(struct notifier_block *this,
- unsigned long event, void *_data)
-{
- struct fimd_context *ctx
- = container_of(this, struct fimd_context, nb_exynos_display);
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
-
- if (ctx->suspended)
- return NOTIFY_DONE;
-
- switch (event) {
- case EXYNOS4_DISPLAY_LV_HF:
- timing->refresh = EXYNOS4_DISPLAY_LV_HF;
- ctx->high_freq = 1;
- break;
- case EXYNOS4_DISPLAY_LV_LF:
- timing->refresh = EXYNOS4_DISPLAY_LV_LF;
- ctx->high_freq = 0;
- break;
- default:
- return NOTIFY_BAD;
- }
-
- exynos_drm_change_clock(ctx);
-
- return NOTIFY_DONE;
-}
-#endif
-
-static ssize_t store_refresh(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
- unsigned long refresh;
- int ret;
-
- if (ctx->dynamic_refresh) {
- ret = kstrtoul(buf, 0, &refresh);
- timing->refresh = refresh;
- if (refresh == 60)
- ctx->high_freq = 1;
- else
- ctx->high_freq = 0;
-
- exynos_drm_change_clock(ctx);
- }
-
- return count;
-}
-
-static ssize_t show_refresh(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", timing->refresh);
-}
-
-static struct device_attribute device_attrs[] = {
- __ATTR(refresh, S_IRUGO|S_IWUSR, show_refresh, store_refresh),
-};
-
-#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
-static void fimd_set_writeback(struct fimd_context *ctx, int enable)
-{
- u32 vidcon0 = readl(ctx->regs + VIDCON0);
- u32 vidcon2 = readl(ctx->regs + VIDCON2);
-
- vidcon0 &= ~VIDCON0_VIDOUT_MASK;
- vidcon2 &= ~(VIDCON2_WB_MASK |
- VIDCON2_WB_SKIP_MASK |
- VIDCON2_TVFORMATSEL_HW_SW_MASK |
- VIDCON2_TVFORMATSEL_MASK);
-
- if (enable) {
- vidcon0 |= VIDCON0_VIDOUT_WB;
- vidcon2 |= (VIDCON2_WB_ENABLE |
- VIDCON2_TVFORMATSEL_SW |
- VIDCON2_TVFORMATSEL_YUV444);
- } else {
- vidcon0 |= VIDCON0_VIDOUT_RGB;
- vidcon2 |= VIDCON2_WB_DISABLE;
- }
-
- writel(vidcon0, ctx->regs + VIDCON0);
- writel(vidcon2, ctx->regs + VIDCON2);
-}
-
-static int fimd_notifier_ctrl(struct notifier_block *this,
- unsigned long event, void *_data)
-{
- struct fimd_context *ctx = container_of(this,
- struct fimd_context, nb_ctrl);
-
- switch (event) {
- case FIMD_GET_LCD_WIDTH: {
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
- int *width = (int *)_data;
-
- *width = timing->xres;
- }
- break;
- case FIMD_GET_LCD_HEIGHT: {
- struct exynos_drm_panel_info *panel = ctx->panel;
- struct fb_videomode *timing = &panel->timing;
- int *height = (int *)_data;
-
- *height = timing->yres;
- }
- break;
- case FIMD_SET_WRITEBACK: {
- unsigned int refresh;
- int *enable = (int *)&_data;
-
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- if (*enable)
- refresh = EXYNOS4_DISPLAY_LV_HF;
- else
- refresh = EXYNOS4_DISPLAY_LV_LF;
- pm_qos_update_request(&ctx->pm_qos,
- refresh);
-#endif
- fimd_set_writeback(ctx, *enable);
- }
- break;
- default:
- /* ToDo : for checking use case */
- DRM_INFO("%s:event[0x%x]\n", __func__, (unsigned int)event);
- break;
- }
-
- return NOTIFY_DONE;
-}
-#endif
-
-static int __devinit fimd_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct fimd_context *ctx;
- struct exynos_drm_subdrv *subdrv;
- struct exynos_drm_fimd_pdata *pdata;
- struct exynos_drm_panel_info *panel;
- struct resource *res;
- int win;
- int i;
- int ret = -EINVAL;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(dev, "no platform data specified\n");
- return -EINVAL;
- }
-
- panel = &pdata->panel;
- if (!panel) {
- dev_err(dev, "panel is null.\n");
- return -EINVAL;
- }
-
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
-
- ctx->bus_clk = clk_get(dev, "lcd");
- if (IS_ERR(ctx->bus_clk)) {
- dev_err(dev, "failed to get bus clock\n");
- ret = PTR_ERR(ctx->bus_clk);
- goto err_clk_get;
- }
-
- clk_enable(ctx->bus_clk);
-
- ctx->lcd_clk = clk_get(dev, "sclk_fimd");
- if (IS_ERR(ctx->lcd_clk)) {
- dev_err(dev, "failed to get lcd clock\n");
- ret = PTR_ERR(ctx->lcd_clk);
- goto err_bus_clk;
- }
-
- clk_enable(ctx->lcd_clk);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "failed to find registers\n");
- ret = -ENOENT;
- goto err_clk;
- }
-
- ctx->regs_res = request_mem_region(res->start, resource_size(res),
- dev_name(dev));
- if (!ctx->regs_res) {
- dev_err(dev, "failed to claim register region\n");
- ret = -ENOENT;
- goto err_clk;
- }
-
- ctx->regs = ioremap(res->start, resource_size(res));
- if (!ctx->regs) {
- dev_err(dev, "failed to map registers\n");
- ret = -ENXIO;
- goto err_req_region_io;
- }
-#ifdef CONFIG_MACH_SLP_NAPLES
- /* Temporary code for trigger*/
- ctx_global = ctx;
-#endif
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(dev, "irq request failed.\n");
- goto err_get_resource;
- }
-
- ctx->irq = res->start;
-
- ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx);
- if (ret < 0) {
- dev_err(dev, "irq request failed.\n");
- goto err_get_resource;
- }
-
- ctx->clkdiv = fimd_calc_clkdiv(ctx, &panel->timing);
- ctx->vidcon0 = pdata->vidcon0;
- ctx->vidcon1 = pdata->vidcon1;
- ctx->default_win = pdata->default_win;
- ctx->dynamic_refresh = pdata->dynamic_refresh;
- ctx->panel = panel;
-
- INIT_WORK(&ctx->work, exynos_fimd_schedule_work);
-
- panel->timing.pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv;
-
- DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n",
- panel->timing.pixclock, ctx->clkdiv);
-
- /* mdnie support. */
- mdnie = s5p_fimd_ext_find_device("mdnie");
- fimd_lite_dev = s5p_fimd_ext_find_device("fimd_lite");
- if (mdnie && fimd_lite_dev) {
- fimd_refresh = kzalloc(sizeof(*fimd_refresh), GFP_KERNEL);
- if (!fimd_refresh) {
- dev_err(dev, "failed to allocate fimd_refresh.\n");
- ret = -ENOMEM;
- goto err_alloc_fail;
- }
-
- fimd_refresh->dynamic_refresh = pdata->dynamic_refresh;
- fimd_refresh->regs = ctx->regs;
- fimd_refresh->clkdiv = ctx->clkdiv;
- }
-
- for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
- ret = device_create_file(&(pdev->dev),
- &device_attrs[i]);
- if (ret)
- break;
- }
-
- if (ret < 0)
- dev_err(&pdev->dev, "failed to add sysfs entries\n");
-
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- ctx->nb_exynos_display.notifier_call = exynos_display_notifier_callback;
- ret = exynos4_display_register_client(&ctx->nb_exynos_display);
- if (ret < 0)
- dev_warn(dev, "failed to register exynos-display notifier\n");
-#endif
-
- dev_info(&pdev->dev, "registered successfully\n");
-
- subdrv = &ctx->subdrv;
-
- subdrv->dev = dev;
- subdrv->manager = &fimd_manager;
- subdrv->probe = fimd_subdrv_probe;
- subdrv->remove = fimd_subdrv_remove;
-
-#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
- ctx->nb_ctrl.notifier_call = fimd_notifier_ctrl;
- ret = fimc_register_client(&ctx->nb_ctrl);
- if (ret) {
- dev_err(dev, "could not register fimd notify callback\n");
- goto err_alloc_fail;
- }
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- pm_qos_add_request(&ctx->pm_qos,
- PM_QOS_DISPLAY_FREQUENCY, EXYNOS4_DISPLAY_LV_LF);
-#endif
-#endif
-
- mutex_init(&ctx->lock);
-
- platform_set_drvdata(pdev, ctx);
-
- pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
- pm_runtime_get_sync(dev);
-
- for (win = 0; win < WINDOWS_NR; win++)
- if (win != ctx->default_win)
- fimd_clear_win(ctx, win);
-
- exynos_drm_subdrv_register(subdrv);
-
- return 0;
-
-err_alloc_fail:
- free_irq(ctx->irq, ctx);
-
-err_get_resource:
- iounmap(ctx->regs);
-
-err_req_region_io:
- release_resource(ctx->regs_res);
- kfree(ctx->regs_res);
-
-err_clk:
- clk_disable(ctx->lcd_clk);
- clk_put(ctx->lcd_clk);
-
-err_bus_clk:
- clk_disable(ctx->bus_clk);
- clk_put(ctx->bus_clk);
-
-err_clk_get:
- kfree(ctx);
- return ret;
-}
-
-static int __devexit fimd_remove(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct fimd_context *ctx = platform_get_drvdata(pdev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_drm_subdrv_unregister(&ctx->subdrv);
-#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
- fimc_unregister_client(&ctx->nb_ctrl);
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- pm_qos_remove_request(&ctx->pm_qos);
-#endif
-#endif
-
- if (ctx->suspended)
- goto out;
-
- pm_runtime_set_suspended(dev);
- pm_runtime_put_sync(dev);
-
-out:
- pm_runtime_disable(dev);
-
- clk_put(ctx->lcd_clk);
- clk_put(ctx->bus_clk);
-
-
-#ifdef CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ
- exynos4_display_unregister_client(&ctx->nb_exynos_display);
-#endif
-
- iounmap(ctx->regs);
- release_resource(ctx->regs_res);
- kfree(ctx->regs_res);
- free_irq(ctx->irq, ctx);
-
- kfree(ctx);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int fimd_suspend(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
-
- if (pm_runtime_suspended(dev))
- return 0;
-
- /*
- * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
- * called here, an error would be returned by that interface
- * because the usage_count of pm runtime is more than 1.
- */
- return fimd_power_on(ctx, false);
-}
-
-static int fimd_resume(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
-
- /*
- * if entered to sleep when lcd panel was on, the usage_count
- * of pm runtime would still be 1 so in this case, fimd driver
- * should be on directly not drawing on pm runtime interface.
- */
- if (!pm_runtime_suspended(dev))
- return fimd_power_on(ctx, true);
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int fimd_runtime_suspend(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return fimd_power_on(ctx, false);
-}
-
-static int fimd_runtime_resume(struct device *dev)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return fimd_power_on(ctx, true);
-}
-#endif
-
-static const struct dev_pm_ops fimd_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
- SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
-};
-
-struct platform_driver fimd_driver = {
- .probe = fimd_probe,
- .remove = __devexit_p(fimd_remove),
- .driver = {
- .name = "s3cfb",
- .owner = THIS_MODULE,
- .pm = &fimd_pm_ops,
- },
-};
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_g2d.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_g2d.c
deleted file mode 100644
index a8f201e..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_g2d.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Authors: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundationr
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/pm_qos_params.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-
-#include "drmP.h"
-#include "exynos_drm.h"
-#include "exynos_drm_drv.h"
-#include "exynos_drm_iommu.h"
-
-#define G2D_HW_MAJOR_VER 4
-#define G2D_HW_MINOR_VER 1
-
-/* vaild register range set from user: 0x0104 ~ 0x0880 */
-#define G2D_VALID_START 0x0104
-#define G2D_VALID_END 0x0880
-
-/* general registers */
-#define G2D_SOFT_RESET 0x0000
-#define G2D_INTEN 0x0004
-#define G2D_INTC_PEND 0x000C
-#define G2D_DMA_SFR_BASE_ADDR 0x0080
-#define G2D_DMA_COMMAND 0x0084
-#define G2D_DMA_STATUS 0x008C
-#define G2D_DMA_HOLD_CMD 0x0090
-
-/* command registers */
-#define G2D_BITBLT_START 0x0100
-
-/* registers for base address */
-#define G2D_SRC_BASE_ADDR 0x0304
-#define G2D_SRC_PLANE2_BASE_ADDR 0x0318
-#define G2D_DST_BASE_ADDR 0x0404
-#define G2D_DST_PLANE2_BASE_ADDR 0x0418
-#define G2D_PAT_BASE_ADDR 0x0500
-#define G2D_MSK_BASE_ADDR 0x0520
-
-/* G2D_SOFT_RESET */
-#define G2D_SFRCLEAR (1 << 1)
-#define G2D_R (1 << 0)
-
-/* G2D_INTEN */
-#define G2D_INTEN_ACF (1 << 3)
-#define G2D_INTEN_UCF (1 << 2)
-#define G2D_INTEN_GCF (1 << 1)
-#define G2D_INTEN_SCF (1 << 0)
-
-/* G2D_INTC_PEND */
-#define G2D_INTP_ACMD_FIN (1 << 3)
-#define G2D_INTP_UCMD_FIN (1 << 2)
-#define G2D_INTP_GCMD_FIN (1 << 1)
-#define G2D_INTP_SCMD_FIN (1 << 0)
-
-/* G2D_DMA_COMMAND */
-#define G2D_DMA_HALT (1 << 2)
-#define G2D_DMA_CONTINUE (1 << 1)
-#define G2D_DMA_START (1 << 0)
-
-/* G2D_DMA_STATUS */
-#define G2D_DMA_LIST_DONE_COUNT (0xFF << 17)
-#define G2D_DMA_BITBLT_DONE_COUNT (0xFFFF << 1)
-#define G2D_DMA_DONE (1 << 0)
-#define G2D_DMA_LIST_DONE_COUNT_OFFSET 17
-
-/* G2D_DMA_HOLD_CMD */
-#define G2D_USET_HOLD (1 << 2)
-#define G2D_LIST_HOLD (1 << 1)
-#define G2D_BITBLT_HOLD (1 << 0)
-
-/* G2D_BITBLT_START */
-#define G2D_START_CASESEL (1 << 2)
-#define G2D_START_NHOLT (1 << 1)
-#define G2D_START_BITBLT (1 << 0)
-
-#define G2D_CMDLIST_SIZE (PAGE_SIZE / 4)
-#define G2D_CMDLIST_NUM 64
-#define G2D_CMDLIST_POOL_SIZE (G2D_CMDLIST_SIZE * G2D_CMDLIST_NUM)
-#define G2D_CMDLIST_DATA_NUM (G2D_CMDLIST_SIZE / sizeof(u32) - 2)
-
-#define MAX_BUF_ADDR_NR 6
-
-/* cmdlist data structure */
-struct g2d_cmdlist {
- u32 head;
- u32 data[G2D_CMDLIST_DATA_NUM];
- u32 last; /* last data offset */
-};
-
-struct drm_exynos_pending_g2d_event {
- struct drm_pending_event base;
- struct drm_exynos_g2d_event event;
-};
-
-struct g2d_cmdlist_node {
- struct list_head list;
- struct g2d_cmdlist *cmdlist;
- unsigned int map_nr;
- void *gem_obj[MAX_BUF_ADDR_NR];
- dma_addr_t dma_addr;
-
- struct drm_exynos_pending_g2d_event *event;
-};
-
-struct g2d_runqueue_node {
- struct list_head list;
- struct list_head run_cmdlist;
- struct list_head event_list;
- struct completion complete;
- int async;
-};
-
-struct g2d_data {
- struct device *dev;
- struct clk *gate_clk;
- struct resource *regs_res;
- void __iomem *regs;
- int irq;
- struct workqueue_struct *g2d_workq;
- struct work_struct runqueue_work;
- struct exynos_drm_subdrv subdrv;
- struct pm_qos_request_list pm_qos;
- bool suspended;
-
- /* cmdlist */
- struct g2d_cmdlist_node *cmdlist_node;
- struct list_head free_cmdlist;
- struct mutex cmdlist_mutex;
- dma_addr_t cmdlist_pool;
- dma_addr_t cmdlist_pool_map;
- void *cmdlist_pool_virt;
-
- /* runqueue*/
- struct g2d_runqueue_node *runqueue_node;
- struct list_head runqueue;
- struct mutex runqueue_mutex;
- struct kmem_cache *runqueue_slab;
-};
-
-static int g2d_init_cmdlist(struct g2d_data *g2d)
-{
- struct device *dev = g2d->dev;
- struct g2d_cmdlist_node *node = g2d->cmdlist_node;
- int nr;
- int ret;
-
- g2d->cmdlist_pool_virt = dma_alloc_coherent(dev, G2D_CMDLIST_POOL_SIZE,
- &g2d->cmdlist_pool, GFP_KERNEL);
- if (!g2d->cmdlist_pool_virt) {
- dev_err(dev, "failed to allocate dma memory\n");
- return -ENOMEM;
- }
-
- /*
- * Allocate device address space for command list pool and then map all
- * pages contained in sg list to iommu table. Command list pool also is
- * accessed by dma through device address with using iommu.
- */
- g2d->cmdlist_pool_map = exynos_drm_iommu_map(dev, g2d->cmdlist_pool,
- G2D_CMDLIST_POOL_SIZE);
- if (!g2d->cmdlist_pool_map) {
- dev_err(dev, "failed map to iommu\n");
- ret = -EFAULT;
- goto err;
- }
-
- node = kcalloc(G2D_CMDLIST_NUM, G2D_CMDLIST_NUM * sizeof(*node),
- GFP_KERNEL);
- if (!node) {
- dev_err(dev, "failed to allocate memory\n");
- ret = -ENOMEM;
- goto err_iommu_unmap;
- }
-
- for (nr = 0; nr < G2D_CMDLIST_NUM; nr++) {
- node[nr].cmdlist =
- g2d->cmdlist_pool_virt + nr * G2D_CMDLIST_SIZE;
- node[nr].dma_addr =
- g2d->cmdlist_pool_map + nr * G2D_CMDLIST_SIZE;
-
- list_add_tail(&node[nr].list, &g2d->free_cmdlist);
- }
-
- return 0;
-
-err_iommu_unmap:
- exynos_drm_iommu_unmap(dev, g2d->cmdlist_pool_map);
-err:
- dma_free_coherent(dev, G2D_CMDLIST_POOL_SIZE, g2d->cmdlist_pool_virt,
- g2d->cmdlist_pool);
- return ret;
-}
-
-static void g2d_fini_cmdlist(struct g2d_data *g2d)
-{
- struct device *dev = g2d->dev;
-
- exynos_drm_iommu_unmap(dev, g2d->cmdlist_pool_map);
-
- kfree(g2d->cmdlist_node);
- dma_free_coherent(dev, G2D_CMDLIST_POOL_SIZE, g2d->cmdlist_pool_virt,
- g2d->cmdlist_pool);
-}
-
-static struct g2d_cmdlist_node *g2d_get_cmdlist(struct g2d_data *g2d)
-{
- struct device *dev = g2d->dev;
- struct g2d_cmdlist_node *node;
-
- mutex_lock(&g2d->cmdlist_mutex);
- if (list_empty(&g2d->free_cmdlist)) {
- dev_err(dev, "there is no free cmdlist\n");
- mutex_unlock(&g2d->cmdlist_mutex);
- return NULL;
- }
-
- node = list_first_entry(&g2d->free_cmdlist, struct g2d_cmdlist_node,
- list);
- list_del_init(&node->list);
- mutex_unlock(&g2d->cmdlist_mutex);
-
- return node;
-}
-
-static void g2d_put_cmdlist(struct g2d_data *g2d, struct g2d_cmdlist_node *node)
-{
- mutex_lock(&g2d->cmdlist_mutex);
- list_move_tail(&node->list, &g2d->free_cmdlist);
- mutex_unlock(&g2d->cmdlist_mutex);
-}
-
-static void g2d_add_cmdlist_to_inuse(struct exynos_drm_g2d_private *g2d_priv,
- struct g2d_cmdlist_node *node)
-{
- struct g2d_cmdlist_node *lnode;
-
- if (list_empty(&g2d_priv->inuse_cmdlist))
- goto add_to_list;
-
- /* this links to base address of new cmdlist */
- lnode = list_entry(g2d_priv->inuse_cmdlist.prev,
- struct g2d_cmdlist_node, list);
- lnode->cmdlist->data[lnode->cmdlist->last] = node->dma_addr;
-
-add_to_list:
- list_add_tail(&node->list, &g2d_priv->inuse_cmdlist);
-
- if (node->event)
- list_add_tail(&node->event->base.link, &g2d_priv->event_list);
-}
-
-static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
- struct g2d_cmdlist_node *node,
- struct drm_device *drm_dev,
- struct drm_file *file)
-{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
- struct g2d_cmdlist *cmdlist = node->cmdlist;
- struct iommu_gem_map_params params;
- unsigned int gem_handle;
- dma_addr_t addr;
- int offset;
- int i;
-
- params.dev = g2d->dev;
- params.drm_dev = drm_dev;
- params.file = file;
-
- for (i = 0; i < node->map_nr; i++) {
- offset = cmdlist->last - (i * 2 + 1);
- gem_handle = cmdlist->data[offset];
-
- addr = exynos_drm_iommu_map_gem(&params,
- &g2d_priv->iommu_map_list,
- gem_handle,
- IOMMU_G2D);
- if (!addr) {
- node->map_nr = i;
- return -EFAULT;
- }
-
- cmdlist->data[offset] = addr;
- node->gem_obj[i] = params.gem_obj;
- }
-
- return 0;
-}
-
-static void g2d_unmap_cmdlist_gem(struct drm_device *drm_dev,
- struct g2d_cmdlist_node *node,
- struct drm_file *file, int dec)
-{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
- struct device *dev = g2d_priv->dev;
- struct g2d_cmdlist *cmdlist = node->cmdlist;
- struct iommu_gem_map_params params;
- struct g2d_data *g2d;
- dma_addr_t addr;
- int offset;
- int i;
-
- g2d = dev_get_drvdata(dev);
- if (!g2d)
- return;
-
- params.dev = dev;
- params.drm_dev = drm_dev;
- params.file = file;
-
- for (i = 0; i < node->map_nr; i++) {
- offset = cmdlist->last - (i * 2 + 1) - dec;
- addr = cmdlist->data[offset];
-
- params.gem_obj = node->gem_obj[i];
-
- exynos_drm_iommu_unmap_gem(&params, addr,
- IOMMU_G2D);
- }
-}
-
-static void g2d_dma_start(struct g2d_data *g2d,
- struct g2d_runqueue_node *runqueue_node)
-{
- struct g2d_cmdlist_node *node =
- list_first_entry(&runqueue_node->run_cmdlist,
- struct g2d_cmdlist_node, list);
-
- pm_runtime_get_sync(g2d->dev);
- clk_enable(g2d->gate_clk);
- pm_qos_update_request(&g2d->pm_qos, 400000);
-
- /* interrupt enable */
- writel_relaxed(G2D_INTEN_ACF | G2D_INTEN_UCF | G2D_INTEN_GCF,
- g2d->regs + G2D_INTEN);
-
- writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR);
- writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND);
-}
-
-static struct g2d_runqueue_node *g2d_get_runqueue_node(struct g2d_data *g2d)
-{
- struct g2d_runqueue_node *runqueue_node;
-
- if (list_empty(&g2d->runqueue))
- return NULL;
-
- runqueue_node = list_first_entry(&g2d->runqueue,
- struct g2d_runqueue_node, list);
- list_del_init(&runqueue_node->list);
- return runqueue_node;
-}
-
-static void g2d_free_runqueue_node(struct g2d_data *g2d,
- struct g2d_runqueue_node *runqueue_node)
-{
- if (!runqueue_node)
- return;
-
- mutex_lock(&g2d->cmdlist_mutex);
- list_splice_tail_init(&runqueue_node->run_cmdlist, &g2d->free_cmdlist);
- mutex_unlock(&g2d->cmdlist_mutex);
-
- kmem_cache_free(g2d->runqueue_slab, runqueue_node);
-}
-
-static void g2d_exec_runqueue(struct g2d_data *g2d)
-{
- g2d->runqueue_node = g2d_get_runqueue_node(g2d);
- if (g2d->runqueue_node)
- g2d_dma_start(g2d, g2d->runqueue_node);
-}
-
-static void g2d_runqueue_worker(struct work_struct *work)
-{
- struct g2d_data *g2d = container_of(work, struct g2d_data,
- runqueue_work);
-
- pm_qos_update_request(&g2d->pm_qos, 0);
-
- mutex_lock(&g2d->runqueue_mutex);
- clk_disable(g2d->gate_clk);
- pm_runtime_put_sync(g2d->dev);
-
- complete(&g2d->runqueue_node->complete);
- if (g2d->runqueue_node->async)
- g2d_free_runqueue_node(g2d, g2d->runqueue_node);
-
- if (g2d->suspended)
- g2d->runqueue_node = NULL;
- else
- g2d_exec_runqueue(g2d);
- mutex_unlock(&g2d->runqueue_mutex);
-}
-
-static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no)
-{
- struct drm_device *drm_dev = g2d->subdrv.drm_dev;
- struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node;
- struct drm_exynos_pending_g2d_event *e;
- struct timeval now;
- unsigned long flags;
-
- if (list_empty(&runqueue_node->event_list))
- return;
-
- e = list_first_entry(&runqueue_node->event_list,
- struct drm_exynos_pending_g2d_event, base.link);
-
- do_gettimeofday(&now);
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
- e->event.cmdlist_no = cmdlist_no;
-
- spin_lock_irqsave(&drm_dev->event_lock, flags);
- list_move_tail(&e->base.link, &e->base.file_priv->event_list);
- wake_up_interruptible(&e->base.file_priv->event_wait);
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-}
-
-static irqreturn_t g2d_irq_handler(int irq, void *dev_id)
-{
- struct g2d_data *g2d = dev_id;
- u32 pending;
-
- pending = readl_relaxed(g2d->regs + G2D_INTC_PEND);
- if (pending)
- writel_relaxed(pending, g2d->regs + G2D_INTC_PEND);
-
- if (pending & G2D_INTP_GCMD_FIN) {
- u32 cmdlist_no = readl_relaxed(g2d->regs + G2D_DMA_STATUS);
-
- cmdlist_no = (cmdlist_no & G2D_DMA_LIST_DONE_COUNT) >>
- G2D_DMA_LIST_DONE_COUNT_OFFSET;
-
- g2d_finish_event(g2d, cmdlist_no);
-
- writel_relaxed(0, g2d->regs + G2D_DMA_HOLD_CMD);
- if (!(pending & G2D_INTP_ACMD_FIN)) {
- writel_relaxed(G2D_DMA_CONTINUE,
- g2d->regs + G2D_DMA_COMMAND);
- }
- }
-
- if (pending & G2D_INTP_ACMD_FIN)
- queue_work(g2d->g2d_workq, &g2d->runqueue_work);
-
- return IRQ_HANDLED;
-}
-
-static int g2d_check_reg_offset(struct device *dev, struct g2d_cmdlist *cmdlist,
- int nr, bool for_addr)
-{
- int reg_offset;
- int index;
- int i;
-
- for (i = 0; i < nr; i++) {
- index = cmdlist->last - 2 * (i + 1);
- reg_offset = cmdlist->data[index] & ~0xfffff000;
-
- if (reg_offset < G2D_VALID_START || reg_offset > G2D_VALID_END)
- goto err;
- if (reg_offset % 4)
- goto err;
-
- switch (reg_offset) {
- case G2D_SRC_BASE_ADDR:
- case G2D_SRC_PLANE2_BASE_ADDR:
- case G2D_DST_BASE_ADDR:
- case G2D_DST_PLANE2_BASE_ADDR:
- case G2D_PAT_BASE_ADDR:
- case G2D_MSK_BASE_ADDR:
- if (!for_addr)
- goto err;
- break;
- default:
- if (for_addr)
- goto err;
- break;
- }
- }
-
- return 0;
-
-err:
- dev_err(dev, "Bad register offset: 0x%x\n", cmdlist->data[index]);
- return -EINVAL;
-}
-
-/* ioctl functions */
-int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file)
-{
- struct drm_exynos_g2d_get_ver *ver = data;
-
- ver->major = G2D_HW_MAJOR_VER;
- ver->minor = G2D_HW_MINOR_VER;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(exynos_g2d_get_ver_ioctl);
-
-int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file)
-{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
- struct device *dev = g2d_priv->dev;
- struct g2d_data *g2d;
- struct drm_exynos_g2d_set_cmdlist *req = data;
- struct drm_exynos_pending_g2d_event *e;
- struct g2d_cmdlist_node *node;
- struct g2d_cmdlist *cmdlist;
- unsigned long flags;
- int size;
- int ret;
-
- if (!dev)
- return -ENODEV;
-
- g2d = dev_get_drvdata(dev);
- if (!g2d)
- return -EFAULT;
-
- node = g2d_get_cmdlist(g2d);
- if (!node)
- return -ENOMEM;
-
- node->event = NULL;
-
- if (req->event_type != G2D_EVENT_NOT) {
- spin_lock_irqsave(&drm_dev->event_lock, flags);
- if (file->event_space < sizeof(e->event)) {
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
- ret = -ENOMEM;
- goto err;
- }
- file->event_space -= sizeof(e->event);
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-
- e = kzalloc(sizeof(*node->event), GFP_KERNEL);
- if (!e) {
- dev_err(dev, "failed to allocate event\n");
-
- spin_lock_irqsave(&drm_dev->event_lock, flags);
- file->event_space += sizeof(e->event);
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-
- ret = -ENOMEM;
- goto err;
- }
-
- e->event.base.type = DRM_EXYNOS_G2D_EVENT;
- e->event.base.length = sizeof(e->event);
- e->event.user_data = req->user_data;
- e->base.event = &e->event.base;
- e->base.file_priv = file;
- e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
-
- node->event = e;
- }
-
- cmdlist = node->cmdlist;
-
- cmdlist->last = 0;
-
- /*
- * If don't clear SFR registers, the cmdlist is affected by register
- * values of previous cmdlist. G2D hw executes SFR clear command and
- * a next command at the same time then the next command is ignored and
- * is executed rightly from next next command, so needs a dummy command
- * to next command of SFR clear command.
- */
- cmdlist->data[cmdlist->last++] = G2D_SOFT_RESET;
- cmdlist->data[cmdlist->last++] = G2D_SFRCLEAR;
- cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR;
- cmdlist->data[cmdlist->last++] = 0;
-
- if (node->event) {
- cmdlist->data[cmdlist->last++] = G2D_DMA_HOLD_CMD;
- cmdlist->data[cmdlist->last++] = G2D_LIST_HOLD;
- }
-
- /* Check size of cmdlist: last 2 is about G2D_BITBLT_START */
- size = cmdlist->last + req->cmd_nr * 2 + req->cmd_gem_nr * 2 + 2;
- if (size > G2D_CMDLIST_DATA_NUM) {
- dev_err(dev, "cmdlist size is too big\n");
- ret = -EINVAL;
- goto err_free_event;
- }
-
- if (copy_from_user(cmdlist->data + cmdlist->last,
- (void __user *)req->cmd,
- sizeof(*req->cmd) * req->cmd_nr)) {
- ret = -EFAULT;
- goto err_free_event;
- }
- cmdlist->last += req->cmd_nr * 2;
-
- ret = g2d_check_reg_offset(dev, cmdlist, req->cmd_nr, false);
- if (ret < 0)
- goto err_free_event;
-
- node->map_nr = req->cmd_gem_nr;
- if (req->cmd_gem_nr) {
- struct drm_exynos_g2d_cmd *cmd_gem = req->cmd_gem;
-
- if (copy_from_user(cmdlist->data + cmdlist->last,
- (void __user *)cmd_gem,
- sizeof(*cmd_gem) * req->cmd_gem_nr)) {
- ret = -EFAULT;
- goto err_free_event;
- }
- cmdlist->last += req->cmd_gem_nr * 2;
-
- ret = g2d_check_reg_offset(dev, cmdlist, req->cmd_gem_nr, true);
- if (ret < 0)
- goto err_free_event;
-
- ret = g2d_map_cmdlist_gem(g2d, node, drm_dev, file);
- if (ret < 0)
- goto err_unmap;
- }
-
- cmdlist->data[cmdlist->last++] = G2D_BITBLT_START;
- cmdlist->data[cmdlist->last++] = G2D_START_BITBLT;
-
- /* head */
- cmdlist->head = cmdlist->last / 2;
-
- /* tail */
- cmdlist->data[cmdlist->last] = 0;
-
- g2d_add_cmdlist_to_inuse(g2d_priv, node);
-
- return 0;
-
-err_unmap:
- g2d_unmap_cmdlist_gem(drm_dev, node, file, 0);
-err_free_event:
- if (node->event) {
- spin_lock_irqsave(&drm_dev->event_lock, flags);
- file->event_space += sizeof(e->event);
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
- kfree(node->event);
- }
-err:
- g2d_put_cmdlist(g2d, node);
- return ret;
-}
-EXPORT_SYMBOL_GPL(exynos_g2d_set_cmdlist_ioctl);
-
-int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file)
-{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
- struct device *dev = g2d_priv->dev;
- struct g2d_data *g2d;
- struct drm_exynos_g2d_exec *req = data;
- struct g2d_runqueue_node *runqueue_node;
- struct list_head *run_cmdlist;
- struct list_head *event_list;
-
- if (!dev)
- return -ENODEV;
-
- g2d = dev_get_drvdata(dev);
- if (!g2d)
- return -EFAULT;
-
- runqueue_node = kmem_cache_alloc(g2d->runqueue_slab, GFP_KERNEL);
- if (!runqueue_node) {
- dev_err(dev, "failed to allocate memory\n");
- return -ENOMEM;
- }
- run_cmdlist = &runqueue_node->run_cmdlist;
- event_list = &runqueue_node->event_list;
- INIT_LIST_HEAD(run_cmdlist);
- INIT_LIST_HEAD(event_list);
- init_completion(&runqueue_node->complete);
- runqueue_node->async = req->async;
-
- list_splice_init(&g2d_priv->inuse_cmdlist, run_cmdlist);
- list_splice_init(&g2d_priv->event_list, event_list);
-
- if (list_empty(run_cmdlist)) {
- dev_err(dev, "there is no inuse cmdlist\n");
- kmem_cache_free(g2d->runqueue_slab, runqueue_node);
- return -EPERM;
- }
-
- mutex_lock(&g2d->runqueue_mutex);
- list_add_tail(&runqueue_node->list, &g2d->runqueue);
- if (!g2d->runqueue_node)
- g2d_exec_runqueue(g2d);
- mutex_unlock(&g2d->runqueue_mutex);
-
- if (runqueue_node->async)
- goto out;
-
- wait_for_completion(&runqueue_node->complete);
- g2d_free_runqueue_node(g2d, runqueue_node);
-
-out:
- return 0;
-}
-EXPORT_SYMBOL_GPL(exynos_g2d_exec_ioctl);
-
-static int g2d_open(struct drm_device *drm_dev, struct device *dev,
- struct drm_file *file)
-{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_g2d_private *g2d_priv;
-
- g2d_priv = kzalloc(sizeof(*g2d_priv), GFP_KERNEL);
- if (!g2d_priv) {
- dev_err(dev, "failed to allocate g2d private data\n");
- return -ENOMEM;
- }
-
- g2d_priv->dev = dev;
- file_priv->g2d_priv = g2d_priv;
-
- INIT_LIST_HEAD(&g2d_priv->inuse_cmdlist);
- INIT_LIST_HEAD(&g2d_priv->event_list);
- INIT_LIST_HEAD(&g2d_priv->iommu_map_list);
-
- return 0;
-}
-
-static void g2d_close(struct drm_device *drm_dev, struct device *dev,
- struct drm_file *file)
-{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
- struct g2d_data *g2d;
- struct g2d_cmdlist_node *node, *n;
- struct iommu_info_node *im, *t_im;
- struct iommu_gem_map_params params;
-
- if (!dev)
- return;
-
- g2d = dev_get_drvdata(dev);
- if (!g2d)
- return;
-
- mutex_lock(&g2d->cmdlist_mutex);
- list_for_each_entry_safe(node, n, &g2d_priv->inuse_cmdlist, list)
- list_move_tail(&node->list, &g2d->free_cmdlist);
- mutex_unlock(&g2d->cmdlist_mutex);
-
- params.dev = dev;
- params.drm_dev = drm_dev;
- params.file = file;
-
- /*
- * unmap all device address spaces from iommu table and
- * release all lists.
- */
- list_for_each_entry_safe(im, t_im, &g2d_priv->iommu_map_list, list) {
- params.gem_obj = im->gem_obj;
-
- exynos_drm_iommu_unmap_gem(&params, im->dma_addr,
- IOMMU_G2D);
- list_del(&im->list);
- kfree(im);
- im = NULL;
- }
-
- kfree(file_priv->g2d_priv);
-}
-
-static int __devinit g2d_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct resource *res;
- struct g2d_data *g2d;
- struct exynos_drm_subdrv *subdrv;
- int ret;
-
- g2d = kzalloc(sizeof(*g2d), GFP_KERNEL);
- if (!g2d) {
- dev_err(dev, "failed to allocate driver data\n");
- return -ENOMEM;
- }
-
- g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab",
- sizeof(struct g2d_runqueue_node), 0, 0, NULL);
- if (!g2d->runqueue_slab) {
- ret = -ENOMEM;
- goto err_free_mem;
- }
-
- g2d->dev = dev;
-
- g2d->g2d_workq = create_singlethread_workqueue("g2d");
- if (!g2d->g2d_workq) {
- dev_err(dev, "failed to create workqueue\n");
- ret = -EINVAL;
- goto err_destroy_slab;
- }
-
- INIT_WORK(&g2d->runqueue_work, g2d_runqueue_worker);
- INIT_LIST_HEAD(&g2d->free_cmdlist);
- INIT_LIST_HEAD(&g2d->runqueue);
-
- mutex_init(&g2d->cmdlist_mutex);
- mutex_init(&g2d->runqueue_mutex);
-
- /* setup device address space for g2d iommu */
- ret = exynos_drm_iommu_setup(dev);
- if (ret < 0) {
- dev_err(dev, "failed to setup iommu\n");
- goto err_destroy_workqueue;
- }
-
- /* enable iommu to g2d hardware */
- ret = exynos_drm_iommu_activate(dev);
- if (ret < 0) {
- dev_err(dev, "failed to activate iommu\n");
- goto err_iommu_cleanup;
- }
-
- ret = g2d_init_cmdlist(g2d);
- if (ret < 0)
- goto err_iommu_deactivate;
-
- g2d->gate_clk = clk_get(dev, "fimg2d");
- if (IS_ERR(g2d->gate_clk)) {
- dev_err(dev, "failed to get gate clock\n");
- ret = PTR_ERR(g2d->gate_clk);
- goto err_fini_cmdlist;
- }
-
- pm_runtime_enable(dev);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "failed to get I/O memory\n");
- ret = -ENOENT;
- goto err_put_clk;
- }
-
- g2d->regs_res = request_mem_region(res->start, resource_size(res),
- dev_name(dev));
- if (!g2d->regs_res) {
- dev_err(dev, "failed to request I/O memory\n");
- ret = -ENOENT;
- goto err_put_clk;
- }
-
- g2d->regs = ioremap(res->start, resource_size(res));
- if (!g2d->regs) {
- dev_err(dev, "failed to remap I/O memory\n");
- ret = -ENXIO;
- goto err_release_res;
- }
-
- g2d->irq = platform_get_irq(pdev, 0);
- if (g2d->irq < 0) {
- dev_err(dev, "failed to get irq\n");
- ret = g2d->irq;
- goto err_unmap_base;
- }
-
- ret = request_irq(g2d->irq, g2d_irq_handler, 0, "drm_g2d", g2d);
- if (ret < 0) {
- dev_err(dev, "irq request failed\n");
- goto err_unmap_base;
- }
-
- platform_set_drvdata(pdev, g2d);
-
- subdrv = &g2d->subdrv;
- subdrv->dev = dev;
- subdrv->open = g2d_open;
- subdrv->close = g2d_close;
-
- ret = exynos_drm_subdrv_register(subdrv);
- if (ret < 0) {
- dev_err(dev, "failed to register drm g2d device\n");
- goto err_free_irq;
- }
-
- pm_qos_add_request(&g2d->pm_qos, PM_QOS_BUS_DMA_THROUGHPUT, 0);
-
- dev_info(dev, "The exynos g2d(ver %d.%d) successfully probed\n",
- G2D_HW_MAJOR_VER, G2D_HW_MINOR_VER);
-
- return 0;
-
-err_free_irq:
- free_irq(g2d->irq, g2d);
-err_unmap_base:
- iounmap(g2d->regs);
-err_release_res:
- release_resource(g2d->regs_res);
- kfree(g2d->regs_res);
-err_put_clk:
- pm_runtime_disable(dev);
- clk_put(g2d->gate_clk);
-err_fini_cmdlist:
- g2d_fini_cmdlist(g2d);
-err_iommu_deactivate:
- exynos_drm_iommu_deactivate(dev);
-err_iommu_cleanup:
- exynos_drm_iommu_cleanup(dev);
-err_destroy_workqueue:
- destroy_workqueue(g2d->g2d_workq);
-err_destroy_slab:
- kmem_cache_destroy(g2d->runqueue_slab);
-err_free_mem:
- kfree(g2d);
- return ret;
-}
-
-static int __devexit g2d_remove(struct platform_device *pdev)
-{
- struct g2d_data *g2d = platform_get_drvdata(pdev);
-
- cancel_work_sync(&g2d->runqueue_work);
- pm_qos_remove_request(&g2d->pm_qos);
- exynos_drm_subdrv_unregister(&g2d->subdrv);
- free_irq(g2d->irq, g2d);
-
- while (g2d->runqueue_node) {
- g2d_free_runqueue_node(g2d, g2d->runqueue_node);
- g2d->runqueue_node = g2d_get_runqueue_node(g2d);
- }
-
- iounmap(g2d->regs);
- release_resource(g2d->regs_res);
- kfree(g2d->regs_res);
-
- pm_runtime_disable(&pdev->dev);
- clk_put(g2d->gate_clk);
-
- g2d_fini_cmdlist(g2d);
- exynos_drm_iommu_deactivate(&pdev->dev);
- exynos_drm_iommu_cleanup(&pdev->dev);
- destroy_workqueue(g2d->g2d_workq);
- kmem_cache_destroy(g2d->runqueue_slab);
- kfree(g2d);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int g2d_suspend(struct device *dev)
-{
- struct g2d_data *g2d = dev_get_drvdata(dev);
-
- mutex_lock(&g2d->runqueue_mutex);
- g2d->suspended = true;
- mutex_unlock(&g2d->runqueue_mutex);
-
- while (g2d->runqueue_node)
- /* FIXME: good range? */
- usleep_range(500, 1000);
-
- flush_work_sync(&g2d->runqueue_work);
-
- return 0;
-}
-
-static int g2d_resume(struct device *dev)
-{
- struct g2d_data *g2d = dev_get_drvdata(dev);
-
- g2d->suspended = false;
- g2d_exec_runqueue(g2d);
-
- return 0;
-}
-#endif
-
-SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);
-
-struct platform_driver g2d_driver = {
- .probe = g2d_probe,
- .remove = __devexit_p(g2d_remove),
- .driver = {
- /* FIXME */
- .name = "s5p-fimg2d",
- .owner = THIS_MODULE,
- .pm = &g2d_pm_ops,
- },
-};
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_g2d.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_g2d.h
deleted file mode 100644
index 1a9c7ca..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_g2d.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Authors: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundationr
- */
-
-#ifdef CONFIG_DRM_EXYNOS_G2D
-extern int exynos_g2d_get_ver_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int exynos_g2d_set_cmdlist_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-#else
-static inline int exynos_g2d_get_ver_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- return -ENODEV;
-}
-
-static inline int exynos_g2d_set_cmdlist_ioctl(struct drm_device *dev,
- void *data,
- struct drm_file *file_priv)
-{
- return -ENODEV;
-}
-
-static inline int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- return -ENODEV;
-}
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_gem.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_gem.c
deleted file mode 100644
index 35d2cd9..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_gem.c
+++ /dev/null
@@ -1,1437 +0,0 @@
-/* exynos_drm_gem.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Author: Inki Dae <inki.dae@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm.h"
-
-#include <drm/exynos_drm.h>
-#include <linux/shmem_fs.h>
-#include <linux/dma-buf.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_gem.h"
-#include "exynos_drm_buf.h"
-#include "exynos_drm_iommu.h"
-
-static struct exynos_drm_private_cb *private_cb;
-
-void exynos_drm_priv_cb_register(struct exynos_drm_private_cb *cb)
-{
- if (cb)
- private_cb = cb;
-}
-
-int register_buf_to_priv_mgr(struct exynos_drm_gem_obj *obj,
- unsigned int *priv_handle, unsigned int *priv_id)
-{
- if (private_cb && private_cb->add_buffer)
- return private_cb->add_buffer(obj, priv_handle, priv_id);
-
- return 0;
-}
-
-static unsigned int convert_to_vm_err_msg(int msg)
-{
- unsigned int out_msg;
-
- switch (msg) {
- case 0:
- case -ERESTARTSYS:
- case -EINTR:
- out_msg = VM_FAULT_NOPAGE;
- break;
-
- case -ENOMEM:
- out_msg = VM_FAULT_OOM;
- break;
-
- default:
- out_msg = VM_FAULT_SIGBUS;
- break;
- }
-
- return out_msg;
-}
-
-static int check_gem_flags(unsigned int flags)
-{
- if (flags & ~(EXYNOS_BO_MASK)) {
- DRM_ERROR("invalid flags.\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int check_cache_flags(unsigned int flags)
-{
- if (flags & ~(EXYNOS_DRM_CACHE_SEL_MASK | EXYNOS_DRM_CACHE_OP_MASK)) {
- DRM_ERROR("invalid flags.\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct vm_area_struct *get_vma(struct vm_area_struct *vma)
-{
- struct vm_area_struct *vma_copy;
-
- vma_copy = kmalloc(sizeof(*vma_copy), GFP_KERNEL);
- if (!vma_copy)
- return NULL;
-
- if (vma->vm_ops && vma->vm_ops->open)
- vma->vm_ops->open(vma);
-
- if (vma->vm_file)
- get_file(vma->vm_file);
-
- memcpy(vma_copy, vma, sizeof(*vma));
-
- vma_copy->vm_mm = NULL;
- vma_copy->vm_next = NULL;
- vma_copy->vm_prev = NULL;
-
- return vma_copy;
-}
-
-static void put_vma(struct vm_area_struct *vma)
-{
- if (!vma)
- return;
-
- if (vma->vm_ops && vma->vm_ops->close)
- vma->vm_ops->close(vma);
-
- if (vma->vm_file)
- fput(vma->vm_file);
-
- kfree(vma);
-}
-
-static void update_vm_cache_attr(struct exynos_drm_gem_obj *obj,
- struct vm_area_struct *vma)
-{
- DRM_DEBUG_KMS("flags = 0x%x\n", obj->flags);
-
- /* non-cachable as default. */
- if (obj->flags & EXYNOS_BO_CACHABLE)
- vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
- else if (obj->flags & EXYNOS_BO_WC)
- vma->vm_page_prot =
- pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
- else
- vma->vm_page_prot =
- pgprot_noncached(vm_get_page_prot(vma->vm_flags));
-}
-
-static unsigned long roundup_gem_size(unsigned long size, unsigned int flags)
-{
- if (!IS_NONCONTIG_BUFFER(flags)) {
- if (size >= SZ_1M)
- return roundup(size, SECTION_SIZE);
- else if (size >= SZ_64K)
- return roundup(size, SZ_64K);
- else
- goto out;
- }
-out:
- return roundup(size, PAGE_SIZE);
-}
-
-struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
- gfp_t gfpmask)
-{
- struct inode *inode;
- struct address_space *mapping;
- struct page *p, **pages;
- int i, npages;
-
- /* This is the shared memory object that backs the GEM resource */
- inode = obj->filp->f_path.dentry->d_inode;
- mapping = inode->i_mapping;
-
- npages = obj->size >> PAGE_SHIFT;
-
- pages = drm_malloc_ab(npages, sizeof(struct page *));
- if (pages == NULL)
- return ERR_PTR(-ENOMEM);
-
- gfpmask |= mapping_gfp_mask(mapping);
-
- for (i = 0; i < npages; i++) {
- p = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
- if (IS_ERR(p))
- goto fail;
- pages[i] = p;
- }
-
- return pages;
-
-fail:
- while (i--)
- page_cache_release(pages[i]);
-
- drm_free_large(pages);
- return ERR_PTR(PTR_ERR(p));
-}
-
-static void exynos_gem_put_pages(struct drm_gem_object *obj,
- struct page **pages,
- bool dirty, bool accessed)
-{
- int i, npages;
-
- npages = obj->size >> PAGE_SHIFT;
-
- for (i = 0; i < npages; i++) {
- if (dirty)
- set_page_dirty(pages[i]);
-
- if (accessed)
- mark_page_accessed(pages[i]);
-
- /* Undo the reference we took when populating the table */
- page_cache_release(pages[i]);
- }
-
- drm_free_large(pages);
-}
-
-static int exynos_drm_gem_map_pages(struct drm_gem_object *obj,
- struct vm_area_struct *vma,
- unsigned long f_vaddr,
- pgoff_t page_offset)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
- struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer;
- unsigned long pfn;
-
- if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
- if (!buf->pages)
- return -EINTR;
-
- pfn = page_to_pfn(buf->pages[page_offset++]);
- } else
- pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;
-
- return vm_insert_mixed(vma, f_vaddr, pfn);
-}
-
-static int exynos_drm_gem_get_pages(struct drm_gem_object *obj)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
- struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer;
- struct scatterlist *sgl;
- struct page **pages;
- unsigned int npages, i = 0;
- int ret;
-
- if (buf->pages) {
- DRM_DEBUG_KMS("already allocated.\n");
- return -EINVAL;
- }
-
- pages = exynos_gem_get_pages(obj, GFP_KERNEL);
- if (IS_ERR(pages)) {
- DRM_ERROR("failed to get pages.\n");
- return PTR_ERR(pages);
- }
-
- npages = obj->size >> PAGE_SHIFT;
- buf->page_size = PAGE_SIZE;
-
- buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
- if (!buf->sgt) {
- DRM_ERROR("failed to allocate sg table.\n");
- ret = -ENOMEM;
- goto err;
- }
-
- ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL);
- if (ret < 0) {
- DRM_ERROR("failed to initialize sg table.\n");
- ret = -EFAULT;
- goto err1;
- }
-
- sgl = buf->sgt->sgl;
-
- /* set all pages to sg list. */
- while (i < npages) {
- sg_set_page(sgl, pages[i], PAGE_SIZE, 0);
- sg_dma_address(sgl) = page_to_phys(pages[i]);
- i++;
- sgl = sg_next(sgl);
- }
-
- /* add some codes for UNCACHED type here. TODO */
-
- buf->pages = pages;
- return ret;
-err1:
- kfree(buf->sgt);
- buf->sgt = NULL;
-err:
- exynos_gem_put_pages(obj, pages, true, false);
- return ret;
-
-}
-
-static void exynos_drm_gem_put_pages(struct drm_gem_object *obj)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
- struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer;
-
- /*
- * if buffer typs is EXYNOS_BO_NONCONTIG then release all pages
- * allocated at gem fault handler.
- */
- sg_free_table(buf->sgt);
- kfree(buf->sgt);
- buf->sgt = NULL;
-
- exynos_gem_put_pages(obj, buf->pages, true, false);
- buf->pages = NULL;
-
- /* add some codes for UNCACHED type here. TODO */
-}
-
-static void exynos_drm_put_userptr(struct drm_gem_object *obj)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct exynos_drm_gem_buf *buf;
- struct vm_area_struct *vma;
- int npages;
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
- buf = exynos_gem_obj->buffer;
- vma = exynos_gem_obj->vma;
-
- if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) {
- put_vma(exynos_gem_obj->vma);
- goto out;
- }
-
- npages = buf->size >> PAGE_SHIFT;
-
- npages--;
- while (npages >= 0) {
- if (buf->write)
- set_page_dirty_lock(buf->pages[npages]);
-
- put_page(buf->pages[npages]);
- npages--;
- }
-
-out:
- kfree(buf->pages);
- buf->pages = NULL;
-
- kfree(buf->sgt);
- buf->sgt = NULL;
-}
-
-static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
- struct drm_file *file_priv,
- unsigned int *handle)
-{
- int ret;
-
- /*
- * allocate a id of idr table where the obj is registered
- * and handle has the id what user can see.
- */
- ret = drm_gem_handle_create(file_priv, obj, handle);
- if (ret)
- return ret;
-
- DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
-
- /* drop reference from allocate - handle holds it now. */
- drm_gem_object_unreference_unlocked(obj);
-
- return 0;
-}
-
-void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
-{
- struct drm_gem_object *obj;
- struct exynos_drm_gem_buf *buf;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- obj = &exynos_gem_obj->base;
- buf = exynos_gem_obj->buffer;
-
- DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count));
-
- /*
- * release a private buffer from its table.
- *
- * this callback will release a ump object only if user requested
- * ump export otherwise just return.
- */
- if (private_cb->release_buffer)
- private_cb->release_buffer(exynos_gem_obj->priv_handle);
-
- if (!buf->pages)
- return;
-
- if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG)
- exynos_drm_gem_put_pages(obj);
- else if (exynos_gem_obj->flags & EXYNOS_BO_USERPTR)
- exynos_drm_put_userptr(obj);
- else
- exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, buf);
-
- exynos_drm_fini_buf(obj->dev, buf);
- exynos_gem_obj->buffer = NULL;
-
- if (obj->map_list.map)
- drm_gem_free_mmap_offset(obj);
-
- /* release file pointer to gem object. */
- drm_gem_object_release(obj);
-
- kfree(exynos_gem_obj);
- exynos_gem_obj = NULL;
-}
-
-struct exynos_drm_gem_obj *exynos_drm_gem_get_obj(struct drm_device *dev,
- unsigned int gem_handle,
- struct drm_file *file_priv)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_gem_object *obj;
-
- obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object.\n");
- return ERR_PTR(-EINVAL);
- }
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- drm_gem_object_unreference_unlocked(obj);
-
- return exynos_gem_obj;
-}
-
-struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
- unsigned long size)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_gem_object *obj;
- int ret;
-
- exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
- if (!exynos_gem_obj) {
- DRM_ERROR("failed to allocate exynos gem object\n");
- return NULL;
- }
-
- exynos_gem_obj->size = size;
- obj = &exynos_gem_obj->base;
-
- ret = drm_gem_object_init(dev, obj, size);
- if (ret < 0) {
- DRM_ERROR("failed to initialize gem object\n");
- kfree(exynos_gem_obj);
- return NULL;
- }
-
- DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
-
- return exynos_gem_obj;
-}
-
-struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
- unsigned int flags,
- unsigned long size)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct exynos_drm_gem_buf *buf;
- int ret;
-
- if (!size) {
- DRM_ERROR("invalid size.\n");
- return ERR_PTR(-EINVAL);
- }
-
- size = roundup_gem_size(size, flags);
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- ret = check_gem_flags(flags);
- if (ret)
- return ERR_PTR(ret);
-
- buf = exynos_drm_init_buf(dev, size);
- if (!buf)
- return ERR_PTR(-ENOMEM);
-
- exynos_gem_obj = exynos_drm_gem_init(dev, size);
- if (!exynos_gem_obj) {
- ret = -ENOMEM;
- goto err_fini_buf;
- }
-
- exynos_gem_obj->buffer = buf;
-
- /* set memory type and cache attribute from user side. */
- exynos_gem_obj->flags = flags;
-
- /*
- * allocate all pages as desired size if user wants to allocate
- * physically non-continuous memory.
- */
- if (flags & EXYNOS_BO_NONCONTIG) {
- ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base);
- if (ret < 0) {
- drm_gem_object_release(&exynos_gem_obj->base);
- goto err_fini_buf;
- }
- } else {
- ret = exynos_drm_alloc_buf(dev, buf, flags);
- if (ret < 0) {
- drm_gem_object_release(&exynos_gem_obj->base);
- goto err_fini_buf;
- }
- }
-
- return exynos_gem_obj;
-
-err_fini_buf:
- exynos_drm_fini_buf(dev, buf);
- return ERR_PTR(ret);
-}
-
-int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_exynos_gem_create *args = data;
- struct exynos_drm_gem_obj *exynos_gem_obj;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);
- if (IS_ERR(exynos_gem_obj))
- return PTR_ERR(exynos_gem_obj);
-
- ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
- &args->handle);
- if (ret) {
- exynos_drm_gem_destroy(exynos_gem_obj);
- return ret;
- }
-
- return 0;
-}
-
-void *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
- unsigned int gem_handle,
- struct drm_file *file_priv)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_gem_object *obj;
-
- obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object.\n");
- return ERR_PTR(-EINVAL);
- }
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
- DRM_DEBUG_KMS("not support NONCONTIG type.\n");
- drm_gem_object_unreference_unlocked(obj);
-
- /* TODO */
- return ERR_PTR(-EINVAL);
- }
-
- return &exynos_gem_obj->buffer->dma_addr;
-}
-
-void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
- unsigned int gem_handle,
- struct drm_file *file_priv)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_gem_object *obj;
-
- obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object.\n");
- return;
- }
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
- DRM_DEBUG_KMS("not support NONCONTIG type.\n");
- drm_gem_object_unreference_unlocked(obj);
-
- /* TODO */
- return;
- }
-
- drm_gem_object_unreference_unlocked(obj);
-
- /*
- * decrease obj->refcount one more time because we has already
- * increased it at exynos_drm_gem_get_dma_addr().
- */
- drm_gem_object_unreference_unlocked(obj);
-}
-
-int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_exynos_gem_map_off *args = data;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n",
- args->handle, (unsigned long)args->offset);
-
- if (!(dev->driver->driver_features & DRIVER_GEM)) {
- DRM_ERROR("does not support GEM.\n");
- return -ENODEV;
- }
-
- return exynos_drm_gem_dumb_map_offset(file_priv, dev, args->handle,
- &args->offset);
-}
-
-static int exynos_drm_gem_mmap_buffer(struct file *filp,
- struct vm_area_struct *vma)
-{
- struct drm_gem_object *obj = filp->private_data;
- struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
- struct exynos_drm_gem_buf *buffer;
- unsigned long pfn, vm_size, usize, uaddr = vma->vm_start;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- vma->vm_flags |= (VM_IO | VM_RESERVED);
-
- update_vm_cache_attr(exynos_gem_obj, vma);
-
- vma->vm_file = filp;
-
- vm_size = usize = vma->vm_end - vma->vm_start;
-
- /*
- * a buffer contains information to physically continuous memory
- * allocated by user request or at framebuffer creation.
- */
- buffer = exynos_gem_obj->buffer;
-
- /* check if user-requested size is valid. */
- if (vm_size > buffer->size)
- return -EINVAL;
-
- if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
- int i = 0;
-
- if (!buffer->pages)
- return -EINVAL;
-
- vma->vm_flags |= VM_MIXEDMAP;
-
- do {
- ret = vm_insert_page(vma, uaddr, buffer->pages[i++]);
- if (ret) {
- DRM_ERROR("failed to remap user space.\n");
- return ret;
- }
-
- uaddr += PAGE_SIZE;
- usize -= PAGE_SIZE;
- } while (usize > 0);
- } else {
- /*
- * get page frame number to physical memory to be mapped
- * to user space.
- */
- pfn = ((unsigned long)exynos_gem_obj->buffer->dma_addr) >>
- PAGE_SHIFT;
-
- DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn);
-
- if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size,
- vma->vm_page_prot)) {
- DRM_ERROR("failed to remap pfn range.\n");
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-
-static const struct file_operations exynos_drm_gem_fops = {
- .mmap = exynos_drm_gem_mmap_buffer,
-};
-
-int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_exynos_gem_mmap *args = data;
- struct drm_gem_object *obj;
- unsigned int addr;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!(dev->driver->driver_features & DRIVER_GEM)) {
- DRM_ERROR("does not support GEM.\n");
- return -ENODEV;
- }
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object.\n");
- return -EINVAL;
- }
-
- obj->filp->f_op = &exynos_drm_gem_fops;
- obj->filp->private_data = obj;
-
- down_write(&current->mm->mmap_sem);
- addr = do_mmap(obj->filp, 0, args->size,
- PROT_READ | PROT_WRITE, MAP_SHARED, 0);
- up_write(&current->mm->mmap_sem);
-
- drm_gem_object_unreference_unlocked(obj);
-
- if (IS_ERR((void *)addr))
- return PTR_ERR((void *)addr);
-
- args->mapped = addr;
-
- DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped);
-
- return 0;
-}
-
-static int exynos_drm_get_userptr(struct drm_device *dev,
- struct exynos_drm_gem_obj *obj,
- unsigned long userptr,
- unsigned int write)
-{
- unsigned int get_npages;
- unsigned long npages = 0;
- struct vm_area_struct *vma;
- struct exynos_drm_gem_buf *buf = obj->buffer;
-
- vma = find_vma(current->mm, userptr);
-
- /* the memory region mmaped with VM_PFNMAP. */
- if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) {
- unsigned long this_pfn, prev_pfn, pa;
- unsigned long start, end, offset;
- struct scatterlist *sgl;
- int ret;
-
- start = userptr;
- offset = userptr & ~PAGE_MASK;
- end = start + buf->size;
- sgl = buf->sgt->sgl;
-
- for (prev_pfn = 0; start < end; start += PAGE_SIZE) {
- ret = follow_pfn(vma, start, &this_pfn);
- if (ret)
- return ret;
-
- if (prev_pfn == 0) {
- pa = this_pfn << PAGE_SHIFT;
- buf->dma_addr = pa + offset;
- } else if (this_pfn != prev_pfn + 1) {
- ret = -EINVAL;
- goto err;
- }
-
- sg_dma_address(sgl) = (pa + offset);
- sg_dma_len(sgl) = PAGE_SIZE;
- prev_pfn = this_pfn;
- pa += PAGE_SIZE;
- npages++;
- sgl = sg_next(sgl);
- }
-
- obj->vma = get_vma(vma);
- if (!obj->vma) {
- ret = -ENOMEM;
- goto err;
- }
-
- buf->pfnmap = true;
-
- return npages;
-err:
- buf->dma_addr = 0;
- return ret;
- }
-
- buf->write = write;
- npages = buf->size >> PAGE_SHIFT;
-
- down_read(&current->mm->mmap_sem);
- get_npages = get_user_pages(current, current->mm, userptr,
- npages, write, 1, buf->pages, NULL);
- up_read(&current->mm->mmap_sem);
- if (get_npages != npages)
- DRM_ERROR("failed to get user_pages.\n");
-
- buf->pfnmap = false;
-
- return get_npages;
-}
-
-int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_exynos_gem_userptr *args = data;
- struct exynos_drm_gem_buf *buf;
- struct scatterlist *sgl;
- unsigned long size, userptr;
- unsigned int npages;
- int ret, get_npages;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!args->size) {
- DRM_ERROR("invalid size.\n");
- return -EINVAL;
- }
-
- ret = check_gem_flags(args->flags);
- if (ret)
- return ret;
-
- size = roundup_gem_size(args->size, EXYNOS_BO_USERPTR);
- userptr = args->userptr;
-
- buf = exynos_drm_init_buf(dev, size);
- if (!buf)
- return -ENOMEM;
-
- exynos_gem_obj = exynos_drm_gem_init(dev, size);
- if (!exynos_gem_obj) {
- ret = -ENOMEM;
- goto err_free_buffer;
- }
-
- buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
- if (!buf->sgt) {
- DRM_ERROR("failed to allocate buf->sgt.\n");
- ret = -ENOMEM;
- goto err_release_gem;
- }
-
- npages = size >> PAGE_SHIFT;
-
- ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL);
- if (ret < 0) {
- DRM_ERROR("failed to initailize sg table.\n");
- goto err_free_sgt;
- }
-
- buf->pages = kzalloc(npages * sizeof(struct page *), GFP_KERNEL);
- if (!buf->pages) {
- DRM_ERROR("failed to allocate buf->pages\n");
- ret = -ENOMEM;
- goto err_free_table;
- }
-
- exynos_gem_obj->buffer = buf;
-
- get_npages = exynos_drm_get_userptr(dev, exynos_gem_obj, userptr, 1);
- if (get_npages != npages) {
- DRM_ERROR("failed to get user_pages.\n");
- ret = get_npages;
- goto err_release_userptr;
- }
-
- ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
- &args->handle);
- if (ret < 0) {
- DRM_ERROR("failed to create gem handle.\n");
- goto err_release_userptr;
- }
-
- sgl = buf->sgt->sgl;
-
- /*
- * if buf->pfnmap is true then update sgl of sgt with pages but
- * if buf->pfnmap is false then it means the sgl was updated already
- * so it doesn't need to update the sgl.
- */
- if (!buf->pfnmap) {
- unsigned int i = 0;
-
- /* set all pages to sg list. */
- while (i < npages) {
- sg_set_page(sgl, buf->pages[i], PAGE_SIZE, 0);
- sg_dma_address(sgl) = page_to_phys(buf->pages[i]);
- i++;
- sgl = sg_next(sgl);
- }
- }
-
- /* always use EXYNOS_BO_USERPTR as memory type for userptr. */
- exynos_gem_obj->flags |= EXYNOS_BO_USERPTR;
-
- return 0;
-
-err_release_userptr:
- get_npages--;
- while (get_npages >= 0)
- put_page(buf->pages[get_npages--]);
- kfree(buf->pages);
- buf->pages = NULL;
-err_free_table:
- sg_free_table(buf->sgt);
-err_free_sgt:
- kfree(buf->sgt);
- buf->sgt = NULL;
-err_release_gem:
- drm_gem_object_release(&exynos_gem_obj->base);
- kfree(exynos_gem_obj);
- exynos_gem_obj = NULL;
-err_free_buffer:
- exynos_drm_free_buf(dev, 0, buf);
- return ret;
-}
-
-int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{ struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_exynos_gem_info *args = data;
- struct drm_gem_object *obj;
-
- mutex_lock(&dev->struct_mutex);
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object.\n");
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
- }
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- args->flags = exynos_gem_obj->flags;
- args->size = exynos_gem_obj->size;
-
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
-int exynos_drm_gem_export_ump_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_gem_object *obj;
- struct drm_exynos_gem_ump *ump = data;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- mutex_lock(&dev->struct_mutex);
-
- obj = drm_gem_object_lookup(dev, file, ump->gem_handle);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object.\n");
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
- }
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- /* register gem buffer to private buffer. */
- ret = register_buf_to_priv_mgr(exynos_gem_obj,
- (unsigned int *)&exynos_gem_obj->priv_handle,
- (unsigned int *)&exynos_gem_obj->priv_id);
- if (ret < 0)
- goto err_unreference_gem;
-
- ump->secure_id = exynos_gem_obj->priv_id;
- drm_gem_object_unreference(obj);
-
- mutex_unlock(&dev->struct_mutex);
-
- DRM_DEBUG_KMS("got secure id = %d\n", ump->secure_id);
-
- return 0;
-
-err_unreference_gem:
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
- return ret;
-
-}
-
-static int exynos_gem_l1_cache_ops(struct drm_device *drm_dev,
- struct drm_exynos_gem_cache_op *op) {
- if (op->flags & EXYNOS_DRM_CACHE_FSH_ALL) {
- /*
- * cortex-A9 core has individual l1 cache so flush l1 caches
- * for all cores but other cores should be considered later.
- * TODO
- */
- if (op->flags & EXYNOS_DRM_ALL_CORES)
- flush_all_cpu_caches();
- else
- __cpuc_flush_user_all();
-
- } else if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE) {
- struct vm_area_struct *vma;
-
- down_read(&current->mm->mmap_sem);
- vma = find_vma(current->mm, op->usr_addr);
- up_read(&current->mm->mmap_sem);
-
- if (!vma) {
- DRM_ERROR("failed to get vma.\n");
- return -EFAULT;
- }
-
- __cpuc_flush_user_range(op->usr_addr, op->usr_addr + op->size,
- vma->vm_flags);
- }
-
- return 0;
-}
-
-static int exynos_gem_l2_cache_ops(struct drm_device *drm_dev,
- struct drm_exynos_gem_cache_op *op) {
- phys_addr_t phy_start, phy_end;
-
- if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE ||
- op->flags & EXYNOS_DRM_CACHE_INV_RANGE ||
- op->flags & EXYNOS_DRM_CACHE_CLN_RANGE) {
- struct vm_area_struct *vma;
-
- down_read(&current->mm->mmap_sem);
- vma = find_vma(current->mm, op->usr_addr);
- up_read(&current->mm->mmap_sem);
-
- if (!vma) {
- DRM_ERROR("failed to get vma.\n");
- return -EFAULT;
- }
-
- /*
- * for range flush to l2 cache, mmaped memory region should
- * be physically continuous because l2 cache uses PIPT.
- */
- if (vma && (vma->vm_flags & VM_PFNMAP)) {
- unsigned long virt_start = op->usr_addr, pfn;
- int ret;
-
- ret = follow_pfn(vma, virt_start, &pfn);
- if (ret < 0) {
- DRM_ERROR("failed to get pfn from usr_addr.\n");
- return ret;
- }
-
- phy_start = pfn << PAGE_SHIFT;
- phy_end = phy_start + op->size;
- } else {
- DRM_ERROR("not mmaped memory region with PFNMAP.\n");
- return -EINVAL;
- }
- }
-
- if (op->flags & EXYNOS_DRM_CACHE_FSH_ALL)
- outer_flush_all();
- else if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE)
- outer_flush_range(phy_start, phy_end);
- else if (op->flags & EXYNOS_DRM_CACHE_INV_ALL)
- outer_inv_all();
- else if (op->flags & EXYNOS_DRM_CACHE_CLN_ALL)
- outer_clean_all();
- else if (op->flags & EXYNOS_DRM_CACHE_INV_RANGE)
- outer_inv_range(phy_start, phy_end);
- else if (op->flags & EXYNOS_DRM_CACHE_CLN_RANGE)
- outer_clean_range(phy_start, phy_end);
- else {
- DRM_ERROR("invalid l2 cache operation.\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-int exynos_drm_gem_cache_op_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_exynos_gem_cache_op *op = data;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- ret = check_cache_flags(op->flags);
- if (ret)
- return -EINVAL;
-
- if (op->flags & EXYNOS_DRM_L1_CACHE ||
- op->flags & EXYNOS_DRM_ALL_CACHES) {
- ret = exynos_gem_l1_cache_ops(drm_dev, op);
- if (ret < 0)
- goto err;
- }
-
- if (op->flags & EXYNOS_DRM_L2_CACHE ||
- op->flags & EXYNOS_DRM_ALL_CACHES)
- ret = exynos_gem_l2_cache_ops(drm_dev, op);
-err:
- return ret;
-}
-
-/* temporary functions. */
-int exynos_drm_gem_get_phy_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_exynos_gem_get_phy *get_phy = data;
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_gem_object *obj;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- mutex_lock(&drm_dev->struct_mutex);
-
- obj = drm_gem_object_lookup(drm_dev, file_priv, get_phy->gem_handle);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object.\n");
- mutex_unlock(&drm_dev->struct_mutex);
- return -EINVAL;
- }
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- /*
- * we can get physical address only for EXYNOS_DRM_GEM_PC memory type.
- */
- if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
- DRM_DEBUG_KMS("not physically continuous memory type.\n");
- drm_gem_object_unreference(obj);
- mutex_unlock(&drm_dev->struct_mutex);
- return -EINVAL;
- }
-
- get_phy->phy_addr = exynos_gem_obj->buffer->dma_addr;
- get_phy->size = exynos_gem_obj->buffer->size;
-
- drm_gem_object_unreference(obj);
- mutex_unlock(&drm_dev->struct_mutex);
-
- return 0;
-}
-
-int exynos_drm_gem_phy_imp_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_exynos_gem_phy_imp *args = data;
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct exynos_drm_gem_buf *buffer;
- int ret = 0;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_gem_obj = exynos_drm_gem_init(drm_dev, args->size);
- if (!exynos_gem_obj)
- return -ENOMEM;
-
- buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
- if (!buffer) {
- DRM_DEBUG_KMS("failed to allocate buffer\n");
- ret = -ENOMEM;
- goto err;
- }
-
- buffer->dma_addr = (dma_addr_t)args->phy_addr;
- buffer->size = args->size;
-
- /*
- * if shared is true, this bufer wouldn't be released.
- * this buffer was allocated by other so don't release it.
- */
- buffer->shared = true;
-
- exynos_gem_obj->buffer = buffer;
-
- ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
- &args->gem_handle);
- if (ret)
- goto err_kfree_buffer;
-
- DRM_DEBUG_KMS("got gem handle = 0x%x\n", args->gem_handle);
-
- return 0;
-
-err_kfree_buffer:
- kfree(buffer);
-err:
- drm_gem_object_release(&exynos_gem_obj->base);
- kfree(exynos_gem_obj);
- return ret;
-}
-
-int exynos_drm_gem_init_object(struct drm_gem_object *obj)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- return 0;
-}
-
-void exynos_drm_gem_free_object(struct drm_gem_object *obj)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct exynos_drm_gem_buf *buf;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
- buf = exynos_gem_obj->buffer;
-
- if (obj->import_attach)
- drm_prime_gem_destroy(obj, buf->sgt);
-
- exynos_drm_gem_destroy(to_exynos_gem_obj(obj));
-}
-
-int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
- struct drm_device *dev,
- struct drm_mode_create_dumb *args)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * alocate memory to be used for framebuffer.
- * - this callback would be called by user application
- * with DRM_IOCTL_MODE_CREATE_DUMB command.
- */
-
- args->pitch = args->width * args->bpp >> 3;
- args->size = PAGE_ALIGN(args->pitch * args->height);
-
- exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);
- if (IS_ERR(exynos_gem_obj))
- return PTR_ERR(exynos_gem_obj);
-
- ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
- &args->handle);
- if (ret) {
- exynos_drm_gem_destroy(exynos_gem_obj);
- return ret;
- }
-
- return 0;
-}
-
-int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
- struct drm_device *dev, uint32_t handle,
- uint64_t *offset)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_gem_object *obj;
- int ret = 0;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- mutex_lock(&dev->struct_mutex);
-
- /*
- * get offset of memory allocated for drm framebuffer.
- * - this callback would be called by user application
- * with DRM_IOCTL_MODE_MAP_DUMB command.
- */
-
- obj = drm_gem_object_lookup(dev, file_priv, handle);
- if (!obj) {
- DRM_ERROR("failed to lookup gem object.\n");
- ret = -EINVAL;
- goto unlock;
- }
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- if (!exynos_gem_obj->base.map_list.map) {
- ret = drm_gem_create_mmap_offset(&exynos_gem_obj->base);
- if (ret)
- goto out;
- }
-
- *offset = (u64)exynos_gem_obj->base.map_list.hash.key << PAGE_SHIFT;
- DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
-
-out:
- drm_gem_object_unreference(obj);
-unlock:
- mutex_unlock(&dev->struct_mutex);
- return ret;
-}
-
-int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
- struct drm_device *dev,
- unsigned int handle)
-{
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * obj->refcount and obj->handle_count are decreased and
- * if both them are 0 then exynos_drm_gem_free_object()
- * would be called by callback to release resources.
- */
- ret = drm_gem_handle_delete(file_priv, handle);
- if (ret < 0) {
- DRM_ERROR("failed to delete drm_gem_handle.\n");
- return ret;
- }
-
- return 0;
-}
-
-void exynos_drm_gem_close_object(struct drm_gem_object *obj,
- struct drm_file *file)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct iommu_gem_map_params params;
- unsigned int type = 0;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* check this gem object was mapped to iommu at here. TODO */
-
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- while (type < MAX_IOMMU_NR) {
- /*
- * unmap device address space already mapped to iommu.
- * - this codes would be performed with user gem release
- * request but in case of no request, when device driver
- * using iommu is released, also same things should be
- * performed by each driver.
- */
- if (exynos_gem_obj->iommu_info.mapped & (1 << type)) {
- dma_addr_t dma_addr;
- struct list_head *list;
-
- params.dev = exynos_gem_obj->iommu_info.devs[type];
- params.drm_dev = obj->dev;
- params.file = file;
- params.gem_obj = exynos_gem_obj;
- dma_addr = exynos_gem_obj->iommu_info.dma_addrs[type];
-
- exynos_drm_iommu_unmap_gem(&params,
- dma_addr,
- type);
-
- exynos_gem_obj->iommu_info.mapped &= ~(1 << type);
- exynos_gem_obj->iommu_info.dma_addrs[type] = 0;
-
- list = exynos_gem_obj->iommu_info.iommu_lists[type];
-
- /*
- * this gem has been unmapped from iommu so also
- * remove a iommu node from current device's own
- * iommu list.
- */
- exynos_drm_remove_iommu_list(list, exynos_gem_obj);
- }
-
- type++;
- }
-}
-
-int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct drm_gem_object *obj = vma->vm_private_data;
- struct drm_device *dev = obj->dev;
- unsigned long f_vaddr;
- pgoff_t page_offset;
- int ret;
-
- page_offset = ((unsigned long)vmf->virtual_address -
- vma->vm_start) >> PAGE_SHIFT;
- f_vaddr = (unsigned long)vmf->virtual_address;
-
- mutex_lock(&dev->struct_mutex);
-
- ret = exynos_drm_gem_map_pages(obj, vma, f_vaddr, page_offset);
- if (ret < 0)
- DRM_ERROR("failed to map pages.\n");
-
- mutex_unlock(&dev->struct_mutex);
-
- return convert_to_vm_err_msg(ret);
-}
-
-int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct exynos_drm_gem_obj *exynos_gem_obj;
- struct drm_gem_object *obj;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* set vm_area_struct. */
- ret = drm_gem_mmap(filp, vma);
- if (ret < 0) {
- DRM_ERROR("failed to mmap.\n");
- return ret;
- }
-
- obj = vma->vm_private_data;
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
- ret = check_gem_flags(exynos_gem_obj->flags);
- if (ret) {
- drm_gem_vm_close(vma);
- drm_gem_free_mmap_offset(obj);
- return ret;
- }
-
- vma->vm_flags &= ~VM_PFNMAP;
- vma->vm_flags |= VM_MIXEDMAP;
-
- update_vm_cache_attr(exynos_gem_obj, vma);
-
- return ret;
-}
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_gem.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_gem.h
deleted file mode 100644
index 1227ae3..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_gem.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/* exynos_drm_gem.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authoer: Inki Dae <inki.dae@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_GEM_H_
-#define _EXYNOS_DRM_GEM_H_
-
-#define to_exynos_gem_obj(x) container_of(x,\
- struct exynos_drm_gem_obj, base)
-
-/* FIMD/HDMI/G2D/FIMC/G3D */
-#define MAX_IOMMU_NR 5
-
-#define IS_NONCONTIG_BUFFER(f) ((f & EXYNOS_BO_NONCONTIG) ||\
- (f & EXYNOS_BO_USERPTR))
-
-struct exynos_drm_private_cb {
- unsigned int (*get_handle)(unsigned int id);
- int (*add_buffer)(void *obj, unsigned int *handle, unsigned int *id);
- void (*release_buffer)(unsigned int handle);
-};
-
-/*
- * exynos drm iommu information structure.
- *
- * @mapped: flag a bit of indicating whether any driver's device address
- * is mapped to its own iommu or not.
- * @dma_addrs: contain device address to each device driver using iommu.
- * @devs: device objects that requested mapping to iommu.
- */
-struct exynos_drm_iommu_info {
- unsigned int mapped;
- dma_addr_t dma_addrs[MAX_IOMMU_NR];
- struct device *devs[MAX_IOMMU_NR];
- struct list_head *iommu_lists[MAX_IOMMU_NR];
- /* TODO. */
-};
-
-/*
- * exynos drm gem buffer structure.
- *
- * @kvaddr: kernel virtual address to allocated memory region.
- * @dma_addr: bus address(accessed by dma) to allocated memory region.
- * - this address could be physical address without IOMMU and
- * device address with IOMMU.
- * @write: whether pages will be written to by the caller.
- * @sgt: sg table to transfer page data.
- * @pages: contain all pages to allocated memory region.
- * @page_size: could be 4K, 64K or 1MB.
- * @size: size of allocated memory region.
- * @shared: indicate shared mfc memory region.
- * (temporarily used and it should be removed later.)
- * @shared_refcount: a reference count for this buffer being shared with others.
- * @pfnmap: indicate whether memory region from userptr is mmaped with
- * VM_PFNMAP or not.
- */
-struct exynos_drm_gem_buf {
- struct device *dev;
- void __iomem *kvaddr;
- dma_addr_t dma_addr;
- unsigned int write;
- struct sg_table *sgt;
- struct page **pages;
- unsigned long page_size;
- unsigned long size;
- bool shared;
- atomic_t shared_refcount;
- bool pfnmap;
-};
-
-/*
- * exynos drm buffer structure.
- *
- * @base: a gem object.
- * - a new handle to this gem object would be created
- * by drm_gem_handle_create().
- * @buffer: a pointer to exynos_drm_gem_buffer object.
- * - contain the information to memory region allocated
- * by user request or at framebuffer creation.
- * continuous memory region allocated by user request
- * or at framebuffer creation.
- * @iommu_info: contain iommu mapping information to each device driver
- * using its own iommu.
- * @size: total memory size to physically non-continuous memory region.
- * @flags: indicate memory type to allocated buffer and cache attruibute.
- * @priv_handle: handle to specific buffer object.
- * @priv_id: unique id to specific buffer object.
- *
- * P.S. this object would be transfered to user as kms_bo.handle so
- * user can access the buffer through kms_bo.handle.
- */
-struct exynos_drm_gem_obj {
- struct drm_gem_object base;
- struct exynos_drm_gem_buf *buffer;
- struct exynos_drm_iommu_info iommu_info;
- unsigned long size;
- struct vm_area_struct *vma;
- unsigned int flags;
- void *dma_buf_vmapping;
- int vmapping_count;
- unsigned int priv_handle;
- unsigned int priv_id;
-};
-
-/* register private callback. */
-void exynos_drm_priv_cb_register(struct exynos_drm_private_cb *cb);
-
-/* register a buffer object to private buffer manager. */
-int register_buf_to_priv_mgr(struct exynos_drm_gem_obj *obj,
- unsigned int *priv_handle, unsigned int *priv_id);
-
-struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
-
-/* destroy a buffer with gem object */
-void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj);
-
-/* create a private gem object and initialize it. */
-struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
- unsigned long size);
-
-/* create a new buffer with gem object */
-struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
- unsigned int flags,
- unsigned long size);
-
-/*
- * request gem object creation and buffer allocation as the size
- * that it is calculated with framebuffer information such as width,
- * height and bpp.
- */
-int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-/*
- * get dma address from gem handle and this function could be used for
- * other drivers such as 2d/3d acceleration drivers.
- * with this function call, gem object reference count would be increased.
- */
-void *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
- unsigned int gem_handle,
- struct drm_file *file_priv);
-
-/*
- * put dma address from gem handle and this function could be used for
- * other drivers such as 2d/3d acceleration drivers.
- * with this function call, gem object reference count would be decreased.
- */
-void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
- unsigned int gem_handle,
- struct drm_file *file_priv);
-
-/* get buffer offset to map to user space. */
-int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-/*
- * mmap the physically continuous memory that a gem object contains
- * to user space.
- */
-int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-/* map user space allocated by malloc to pages. */
-int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-/* get buffer information to memory region allocated by gem. */
-int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-/* initialize gem object. */
-int exynos_drm_gem_init_object(struct drm_gem_object *obj);
-
-/* free gem object. */
-void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj);
-
-/* create memory region for drm framebuffer. */
-int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
- struct drm_device *dev,
- struct drm_mode_create_dumb *args);
-
-/* map memory region for drm framebuffer to user space. */
-int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
- struct drm_device *dev, uint32_t handle,
- uint64_t *offset);
-
-/*
- * destroy memory region allocated.
- * - a gem handle and physical memory region pointed by a gem object
- * would be released by drm_gem_handle_delete().
- */
-int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
- struct drm_device *dev,
- unsigned int handle);
-
-/* page fault handler and mmap fault address(virtual) to physical memory. */
-int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-
-/* set vm_flags and we can change the vm attribute to other one at here. */
-int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
-
-/* get ump sequre id for UMP. */
-int exynos_drm_gem_export_ump_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file);
-
-/* do user desired cache operation. */
-int exynos_drm_gem_cache_op_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file_priv);
-
-/* temporary functions. */
-/* get physical address from a gem. */
-int exynos_drm_gem_get_phy_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file_priv);
-/* import physical memory to a gem. */
-int exynos_drm_gem_phy_imp_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file_priv);
-
-void exynos_drm_gem_close_object(struct drm_gem_object *obj,
- struct drm_file *file);
-
-struct exynos_drm_gem_obj *exynos_drm_gem_get_obj(struct drm_device *dev,
- unsigned int gem_handle,
- struct drm_file *file_priv);
-
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_hdmi.c
deleted file mode 100644
index 5d9d2c2..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_hdmi.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include "drmP.h"
-
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/exynos_drm.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_hdmi.h"
-
-#define to_context(dev) platform_get_drvdata(to_platform_device(dev))
-#define to_subdrv(dev) to_context(dev)
-#define get_ctx_from_subdrv(subdrv) container_of(subdrv,\
- struct drm_hdmi_context, subdrv);
-
-/* these callback points shoud be set by specific drivers. */
-static struct exynos_hdmi_ops *hdmi_ops;
-static struct exynos_mixer_ops *mixer_ops;
-
-struct drm_hdmi_context {
- struct exynos_drm_subdrv subdrv;
- struct exynos_drm_hdmi_context *hdmi_ctx;
- struct exynos_drm_hdmi_context *mixer_ctx;
-
- bool enabled[MIXER_WIN_NR];
-};
-
-void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ops)
- hdmi_ops = ops;
-}
-
-void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ops)
- mixer_ops = ops;
-}
-
-static bool drm_hdmi_is_connected(struct device *dev)
-{
- struct drm_hdmi_context *ctx = to_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->is_connected)
- return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);
-
- return false;
-}
-
-static int drm_hdmi_get_edid(struct device *dev,
- struct drm_connector *connector, u8 *edid, int len)
-{
- struct drm_hdmi_context *ctx = to_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->get_edid)
- return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid,
- len);
-
- return 0;
-}
-
-static int drm_hdmi_check_timing(struct device *dev, void *timing)
-{
- struct drm_hdmi_context *ctx = to_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->check_timing)
- return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);
-
- return 0;
-}
-
-static int drm_hdmi_power_on(struct device *dev, int mode)
-{
- struct drm_hdmi_context *ctx = to_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->power_on)
- return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode);
-
- return 0;
-}
-
-static struct exynos_drm_display_ops drm_hdmi_display_ops = {
- .type = EXYNOS_DISPLAY_TYPE_HDMI,
- .is_connected = drm_hdmi_is_connected,
- .get_edid = drm_hdmi_get_edid,
- .check_timing = drm_hdmi_check_timing,
- .power_on = drm_hdmi_power_on,
-};
-
-static int drm_hdmi_enable_vblank(struct device *subdrv_dev)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
- struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct exynos_drm_manager *manager = subdrv->manager;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (mixer_ops && mixer_ops->enable_vblank)
- return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx,
- manager->pipe);
-
- return 0;
-}
-
-static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (mixer_ops && mixer_ops->disable_vblank)
- return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
-}
-
-static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
- struct drm_connector *connector,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->mode_fixup)
- hdmi_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, mode,
- adjusted_mode);
-}
-
-static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->mode_set)
- hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
-}
-
-static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
- unsigned int *width, unsigned int *height)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->get_max_resol)
- hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
-}
-
-static void drm_hdmi_commit(struct device *subdrv_dev)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (hdmi_ops && hdmi_ops->commit)
- hdmi_ops->commit(ctx->hdmi_ctx->ctx);
-}
-
-static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (mixer_ops && mixer_ops->dpms)
- mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
-
- if (hdmi_ops && hdmi_ops->dpms)
- hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
-}
-
-static void drm_hdmi_apply(struct device *subdrv_dev)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
- int i;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- for (i = 0; i < MIXER_WIN_NR; i++) {
- if (!ctx->enabled[i])
- continue;
- if (mixer_ops && mixer_ops->win_commit)
- mixer_ops->win_commit(ctx->mixer_ctx->ctx, i);
- }
-
- if (hdmi_ops && hdmi_ops->commit)
- hdmi_ops->commit(ctx->hdmi_ctx->ctx);
-}
-
-static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
- .dpms = drm_hdmi_dpms,
- .apply = drm_hdmi_apply,
- .enable_vblank = drm_hdmi_enable_vblank,
- .disable_vblank = drm_hdmi_disable_vblank,
- .mode_fixup = drm_hdmi_mode_fixup,
- .mode_set = drm_hdmi_mode_set,
- .get_max_resol = drm_hdmi_get_max_resol,
- .commit = drm_hdmi_commit,
-};
-
-static void drm_mixer_mode_set(struct device *subdrv_dev,
- struct exynos_drm_overlay *overlay)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (mixer_ops && mixer_ops->win_mode_set)
- mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
-}
-
-static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
- int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (win < 0 || win > MIXER_WIN_NR) {
- DRM_ERROR("mixer window[%d] is wrong\n", win);
- return;
- }
-
- if (mixer_ops && mixer_ops->win_commit)
- mixer_ops->win_commit(ctx->mixer_ctx->ctx, win);
-
- ctx->enabled[win] = true;
-}
-
-static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
- int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (win < 0 || win > MIXER_WIN_NR) {
- DRM_ERROR("mixer window[%d] is wrong\n", win);
- return;
- }
-
- if (mixer_ops && mixer_ops->win_disable)
- mixer_ops->win_disable(ctx->mixer_ctx->ctx, win);
-
- ctx->enabled[win] = false;
-}
-
-static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
- .mode_set = drm_mixer_mode_set,
- .commit = drm_mixer_commit,
- .disable = drm_mixer_disable,
-};
-
-static struct exynos_drm_manager hdmi_manager = {
- .pipe = -1,
- .ops = &drm_hdmi_manager_ops,
- .overlay_ops = &drm_hdmi_overlay_ops,
- .display_ops = &drm_hdmi_display_ops,
-};
-
-static int hdmi_subdrv_probe(struct drm_device *drm_dev,
- struct device *dev)
-{
- struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
- struct drm_hdmi_context *ctx;
- struct platform_device *pdev = to_platform_device(dev);
- struct exynos_drm_common_hdmi_pd *pd;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- pd = pdev->dev.platform_data;
-
- if (!pd) {
- DRM_DEBUG_KMS("platform data is null.\n");
- return -EFAULT;
- }
-
- if (!pd->hdmi_dev) {
- DRM_DEBUG_KMS("hdmi device is null.\n");
- return -EFAULT;
- }
-
- if (!pd->mixer_dev) {
- DRM_DEBUG_KMS("mixer device is null.\n");
- return -EFAULT;
- }
-
- ctx = get_ctx_from_subdrv(subdrv);
-
- ctx->hdmi_ctx = (struct exynos_drm_hdmi_context *)
- to_context(pd->hdmi_dev);
- if (!ctx->hdmi_ctx) {
- DRM_DEBUG_KMS("hdmi context is null.\n");
- return -EFAULT;
- }
-
- ctx->hdmi_ctx->drm_dev = drm_dev;
-
- ctx->mixer_ctx = (struct exynos_drm_hdmi_context *)
- to_context(pd->mixer_dev);
- if (!ctx->mixer_ctx) {
- DRM_DEBUG_KMS("mixer context is null.\n");
- return -EFAULT;
- }
-
- ctx->mixer_ctx->drm_dev = drm_dev;
-
- return 0;
-}
-
-static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct exynos_drm_subdrv *subdrv;
- struct drm_hdmi_context *ctx;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx) {
- DRM_LOG_KMS("failed to alloc common hdmi context.\n");
- return -ENOMEM;
- }
-
- subdrv = &ctx->subdrv;
-
- subdrv->dev = dev;
- subdrv->manager = &hdmi_manager;
- subdrv->probe = hdmi_subdrv_probe;
-
- platform_set_drvdata(pdev, subdrv);
-
- exynos_drm_subdrv_register(subdrv);
-
- return 0;
-}
-
-static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)
-{
- struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_drm_subdrv_unregister(&ctx->subdrv);
- kfree(ctx);
-
- return 0;
-}
-
-struct platform_driver exynos_drm_common_hdmi_driver = {
- .probe = exynos_drm_hdmi_probe,
- .remove = __devexit_p(exynos_drm_hdmi_remove),
- .driver = {
- .name = "exynos-drm-hdmi",
- .owner = THIS_MODULE,
- },
-};
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_hdmi.h
deleted file mode 100644
index bd81269..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_hdmi.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* exynos_drm_hdmi.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authoer: Inki Dae <inki.dae@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_HDMI_H_
-#define _EXYNOS_DRM_HDMI_H_
-
-#define MIXER_WIN_NR 3
-#define MIXER_DEFAULT_WIN 0
-
-/*
- * exynos hdmi common context structure.
- *
- * @drm_dev: pointer to drm_device.
- * @ctx: pointer to the context of specific device driver.
- * this context should be hdmi_context or mixer_context.
- */
-struct exynos_drm_hdmi_context {
- struct drm_device *drm_dev;
- void *ctx;
-};
-
-struct exynos_hdmi_ops {
- /* display */
- bool (*is_connected)(void *ctx);
- int (*get_edid)(void *ctx, struct drm_connector *connector,
- u8 *edid, int len);
- int (*check_timing)(void *ctx, void *timing);
- int (*power_on)(void *ctx, int mode);
-
- /* manager */
- void (*mode_fixup)(void *ctx, struct drm_connector *connector,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
- void (*mode_set)(void *ctx, void *mode);
- void (*get_max_resol)(void *ctx, unsigned int *width,
- unsigned int *height);
- void (*commit)(void *ctx);
- void (*dpms)(void *ctx, int mode);
-};
-
-struct exynos_mixer_ops {
- /* manager */
- int (*enable_vblank)(void *ctx, int pipe);
- void (*disable_vblank)(void *ctx);
- void (*dpms)(void *ctx, int mode);
-
- /* overlay */
- void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
- void (*win_commit)(void *ctx, int zpos);
- void (*win_disable)(void *ctx, int zpos);
-};
-
-void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops);
-void exynos_mixer_ops_register(struct exynos_mixer_ops *ops);
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_iommu.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_iommu.c
deleted file mode 100644
index f2ffa68..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_iommu.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/* exynos_drm_iommu.c
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * Author: Inki Dae <inki.dae@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm.h"
-
-#include <drm/exynos_drm.h>
-
-#include <plat/s5p-iovmm.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_gem.h"
-#include "exynos_drm_iommu.h"
-
-static DEFINE_MUTEX(iommu_mutex);
-
-struct exynos_iommu_ops {
- int (*setup)(struct device *dev);
- void (*cleanup)(struct device *dev);
- int (*activate)(struct device *dev);
- void (*deactivate)(struct device *dev);
- dma_addr_t (*map)(struct device *dev, struct scatterlist *sg,
- off_t offset, size_t size);
- void (*unmap)(struct device *dev, dma_addr_t iova);
-};
-
-static const struct exynos_iommu_ops iommu_ops = {
- .setup = iovmm_setup,
- .cleanup = iovmm_cleanup,
- .activate = iovmm_activate,
- .deactivate = iovmm_deactivate,
- .map = iovmm_map,
- .unmap = iovmm_unmap
-};
-
-static bool check_iommu_map_params(struct iommu_gem_map_params *params)
-{
- if (!params) {
- DRM_ERROR("params is null.\n");
- return false;
- }
-
- if (!params->dev || !params->drm_dev || !params->file) {
- DRM_ERROR("invalid params.\n");
- return false;
- }
-
- return true;
-}
-
-void exynos_drm_remove_iommu_list(struct list_head *iommu_list,
- void *gem_obj)
-{
- struct iommu_info_node *im, *t_im;
-
- list_for_each_entry_safe(im, t_im, iommu_list, list) {
- if (im->gem_obj == gem_obj) {
- list_del(&im->list);
- kfree(im);
- im = NULL;
- break;
- }
- }
-
-}
-
-dma_addr_t exynos_drm_iommu_map_gem(struct iommu_gem_map_params *params,
- struct list_head *iommu_list,
- unsigned int gem_handle,
- enum iommu_types type)
-{
- struct sg_table *sgt;
- struct iommu_info_node *node;
- struct exynos_drm_gem_obj *obj;
- dma_addr_t dma_addr;
-
- if (!is_iommu_type_valid(type)) {
- DRM_ERROR("invalid iommu type.\n");
- return 0;
- }
-
- if (!check_iommu_map_params(params))
- return 0;
-
- /* get gem object from specific gem framework. */
- obj = exynos_drm_gem_get_obj(params->drm_dev, gem_handle,
- params->file);
- if (IS_ERR(obj))
- return 0;
-
- mutex_lock(&iommu_mutex);
-
- /*
- * if this gem object had already been mapped to iommu then
- * return dma address mapped before this time.
- */
- if (obj->iommu_info.mapped & (1 << type)) {
- DRM_DEBUG_KMS("already mapped to iommu");
- mutex_unlock(&iommu_mutex);
- return obj->iommu_info.dma_addrs[type];
- }
-
- sgt = obj->buffer->sgt;
-
- /*
- * if not using iommu, just return base address to physical
- * memory region of the gem.
- */
- if (!iommu_ops.map) {
- mutex_unlock(&iommu_mutex);
- return sg_dma_address(&sgt->sgl[0]);
- }
- mutex_unlock(&iommu_mutex);
-
- /*
- * allocate device address space for this driver and then
- * map all pages contained in sg list to iommu table.
- */
- dma_addr = iommu_ops.map(params->dev, sgt->sgl, (off_t)0,
- (size_t)obj->size);
- if (!dma_addr) {
- mutex_unlock(&iommu_mutex);
- return dma_addr;
- }
-
- mutex_lock(&iommu_mutex);
-
- /*
- * check map flag bit and device address mapped to iommu.
- * this data would be used to avoid duplicated mapping.
- */
- obj->iommu_info.mapped |= (1 << type);
- obj->iommu_info.dma_addrs[type] = dma_addr;
- obj->iommu_info.devs[type] = params->dev;
- obj->iommu_info.iommu_lists[type] = iommu_list;
-
- params->gem_obj = obj;
-
- /*
- * this gem object is referenced by this driver so
- * the object refcount should be increased.
- */
- drm_gem_object_reference(&obj->base);
-
- node = kzalloc(sizeof(*node), GFP_KERNEL);
- if (!node) {
- DRM_ERROR("failed to allocate iommu node.\n");
- dma_addr = 0;
- goto err;
- }
-
- node->gem_obj = obj;
- node->dma_addr = dma_addr;
- mutex_unlock(&iommu_mutex);
-
- list_add_tail(&node->list, iommu_list);
-
- return dma_addr;
-err:
- mutex_unlock(&iommu_mutex);
- iommu_ops.unmap(params->dev, dma_addr);
- return dma_addr;
-}
-
-void exynos_drm_iommu_unmap_gem(struct iommu_gem_map_params *params,
- dma_addr_t dma_addr,
- enum iommu_types type)
-{
- struct exynos_drm_gem_obj *obj;
-
- if (!iommu_ops.unmap)
- return;
-
- if (!is_iommu_type_valid(type)) {
- DRM_ERROR("invalid iommu type.\n");
- return;
- }
-
- if (!check_iommu_map_params(params))
- return;
-
- if (!params->gem_obj)
- return;
-
- obj = (struct exynos_drm_gem_obj *)params->gem_obj;
-
- mutex_lock(&iommu_mutex);
- if (!(obj->iommu_info.mapped & (1 << type))) {
- DRM_DEBUG_KMS("not already mapped to iommu so just return\n");
- mutex_unlock(&iommu_mutex);
- return;
- }
-
- /* uncheck map flag bit. */
- obj->iommu_info.mapped &= ~(1 << type);
- obj->iommu_info.dma_addrs[type] = 0;
- mutex_unlock(&iommu_mutex);
-
- iommu_ops.unmap(params->dev, dma_addr);
-
- /*
- * drop this gem object refcount to release allocated buffer
- * and resources.
- */
- drm_gem_object_unreference_unlocked(&obj->base);
-}
-
-dma_addr_t exynos_drm_iommu_map(struct device *dev, dma_addr_t paddr,
- size_t size)
-{
- struct sg_table *sgt;
- struct scatterlist *sgl;
- dma_addr_t dma_addr = 0, tmp_addr;
- unsigned int npages, i = 0;
- int ret;
-
- /* if not using iommu, just return paddr. */
- if (!iommu_ops.map)
- return paddr;
-
- npages = size >> PAGE_SHIFT;
-
- sgt = kzalloc(sizeof(struct sg_table) * npages, GFP_KERNEL);
- if (!sgt) {
- dev_err(dev, "failed to allocate sg table.\n");
- return dma_addr;
- }
-
- ret = sg_alloc_table(sgt, npages, GFP_KERNEL);
- if (ret < 0) {
- dev_err(dev, "failed to initialize sg table.\n");
- goto err;
- }
-
- sgl = sgt->sgl;
- tmp_addr = paddr;
-
- while (i < npages) {
- struct page *page = phys_to_page(tmp_addr);
- sg_set_page(sgl, page, PAGE_SIZE, 0);
- sg_dma_len(sgl) = PAGE_SIZE;
- tmp_addr += PAGE_SIZE;
- i++;
- sgl = sg_next(sgl);
- }
-
- /*
- * allocate device address space for this driver and then
- * map all pages contained in sg list to iommu table.
- */
- dma_addr = iommu_ops.map(dev, sgt->sgl, (off_t)0, (size_t)size);
- if (!dma_addr)
- dev_err(dev, "failed to map cmdlist pool.\n");
-
- sg_free_table(sgt);
-err:
- kfree(sgt);
- sgt = NULL;
-
- return dma_addr;
-}
-
-
-void exynos_drm_iommu_unmap(struct device *dev, dma_addr_t dma_addr)
-{
- if (iommu_ops.unmap)
- iommu_ops.unmap(dev, dma_addr);
-}
-
-int exynos_drm_iommu_setup(struct device *dev)
-{
- /*
- * allocate device address space to this driver and add vmm object
- * to s5p_iovmm_list. please know that each iommu will use
- * 1GB as its own device address apace.
- *
- * the device address space : 0x80000000 ~ 0xA0000000
- */
- if (iommu_ops.setup)
- return iommu_ops.setup(dev);
-
- return 0;
-}
-
-int exynos_drm_iommu_activate(struct device *dev)
-{
- if (iommu_ops.activate)
- return iovmm_activate(dev);
-
- return 0;
-}
-
-void exynos_drm_iommu_deactivate(struct device *dev)
-{
- if (iommu_ops.deactivate)
- iommu_ops.deactivate(dev);
-}
-
-void exynos_drm_iommu_cleanup(struct device *dev)
-{
- if (iommu_ops.cleanup)
- iommu_ops.cleanup(dev);
-}
-
-MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC DRM IOMMU Framework");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_iommu.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_iommu.h
deleted file mode 100644
index aa267ba..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_iommu.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* exynos_drm_iommu.h
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * Authoer: Inki Dae <inki.dae@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_IOMMU_H_
-#define _EXYNOS_DRM_IOMMU_H_
-
-enum iommu_types {
- IOMMU_FIMD = 0,
- IOMMU_HDMI,
- IOMMU_G2D,
- IOMMU_FIMC,
- IOMMU_G3D,
- IOMMU_ROTATOR,
- IOMMU_MASK = 0x3f
-};
-
-struct iommu_gem_map_params {
- struct device *dev;
- struct drm_device *drm_dev;
- struct drm_file *file;
- void *gem_obj;
-};
-
-#define is_iommu_type_valid(t) (((1 << (t)) & ~(IOMMU_MASK)) ? false : true)
-
-void exynos_drm_remove_iommu_list(struct list_head *iommu_list,
- void *gem_obj);
-
-/* get all pages to gem object and map them to iommu table. */
-dma_addr_t exynos_drm_iommu_map_gem(struct iommu_gem_map_params *params,
- struct list_head *iommu_list,
- unsigned int gem_handle,
- enum iommu_types type);
-
-/* unmap device address space to gem object from iommu table. */
-void exynos_drm_iommu_unmap_gem(struct iommu_gem_map_params *params,
- dma_addr_t dma_addr,
- enum iommu_types type);
-
-/* map physical memory region pointed by paddr to iommu table. */
-dma_addr_t exynos_drm_iommu_map(struct device *dev, dma_addr_t paddr,
- size_t size);
-
-/* unmap device address space pointed by dma_addr from iommu table. */
-void exynos_drm_iommu_unmap(struct device *dev, dma_addr_t dma_addr);
-
-/* setup device address space for device iommu. */
-int exynos_drm_iommu_setup(struct device *dev);
-
-int exynos_drm_iommu_activate(struct device *dev);
-
-void exynos_drm_iommu_deactivate(struct device *dev);
-
-/* clean up allocated device address space for device iommu. */
-void exynos_drm_iommu_cleanup(struct device *dev);
-
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_plane.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_plane.c
deleted file mode 100644
index c4c6525..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_plane.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include "drmP.h"
-
-#include "exynos_drm.h"
-#include "exynos_drm_crtc.h"
-#include "exynos_drm_drv.h"
-#include "exynos_drm_encoder.h"
-
-struct exynos_plane {
- struct drm_plane base;
- struct exynos_drm_overlay overlay;
- bool enabled;
-};
-
-static const uint32_t formats[] = {
- DRM_FORMAT_XRGB8888,
- DRM_FORMAT_ARGB8888,
- DRM_FORMAT_NV12,
- DRM_FORMAT_NV12M,
- DRM_FORMAT_NV12MT,
-};
-
-static int
-exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
-{
- struct exynos_plane *exynos_plane =
- container_of(plane, struct exynos_plane, base);
- struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
- struct exynos_drm_crtc_pos pos;
- int ret;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos));
- pos.crtc_x = crtc_x;
- pos.crtc_y = crtc_y;
- pos.crtc_w = crtc_w;
- pos.crtc_h = crtc_h;
-
- /* considering 16.16 fixed point of source values */
- pos.fb_x = src_x >> 16;
- pos.fb_y = src_y >> 16;
- pos.src_w = src_w >> 16;
- pos.src_h = src_h >> 16;
-
- ret = exynos_drm_overlay_update(overlay, fb, &crtc->mode, &pos);
- if (ret < 0)
- return ret;
-
- exynos_drm_fn_encoder(crtc, overlay,
- exynos_drm_encoder_crtc_mode_set);
- exynos_drm_fn_encoder(crtc, &overlay->zpos,
- exynos_drm_encoder_crtc_plane_commit);
-
- exynos_plane->enabled = true;
-
- return 0;
-}
-
-static int exynos_disable_plane(struct drm_plane *plane)
-{
- struct exynos_plane *exynos_plane =
- container_of(plane, struct exynos_plane, base);
- struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- if (!exynos_plane->enabled)
- return 0;
-
- exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
- exynos_drm_encoder_crtc_disable);
-
- exynos_plane->enabled = false;
- exynos_plane->overlay.zpos = DEFAULT_ZPOS;
-
- return 0;
-}
-
-static void exynos_plane_destroy(struct drm_plane *plane)
-{
- struct exynos_plane *exynos_plane =
- container_of(plane, struct exynos_plane, base);
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- exynos_disable_plane(plane);
- drm_plane_cleanup(plane);
- kfree(exynos_plane);
-}
-
-static struct drm_plane_funcs exynos_plane_funcs = {
- .update_plane = exynos_update_plane,
- .disable_plane = exynos_disable_plane,
- .destroy = exynos_plane_destroy,
-};
-
-int exynos_plane_init(struct drm_device *dev, unsigned int nr)
-{
- struct exynos_plane *exynos_plane;
- uint32_t possible_crtcs;
-
- exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL);
- if (!exynos_plane)
- return -ENOMEM;
-
- /* all CRTCs are available */
- possible_crtcs = (1 << MAX_CRTC) - 1;
-
- exynos_plane->overlay.zpos = DEFAULT_ZPOS;
-
- return drm_plane_init(dev, &exynos_plane->base, possible_crtcs,
- &exynos_plane_funcs, formats, ARRAY_SIZE(formats),
- false);
-}
-
-int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_exynos_plane_set_zpos *zpos_req = data;
- struct drm_mode_object *obj;
- struct drm_plane *plane;
- struct exynos_plane *exynos_plane;
- int ret = 0;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return -EINVAL;
-
- if (zpos_req->zpos < 0 || zpos_req->zpos >= MAX_PLANE) {
- if (zpos_req->zpos != DEFAULT_ZPOS) {
- DRM_ERROR("zpos not within limits\n");
- return -EINVAL;
- }
- }
-
- mutex_lock(&dev->mode_config.mutex);
-
- obj = drm_mode_object_find(dev, zpos_req->plane_id,
- DRM_MODE_OBJECT_PLANE);
- if (!obj) {
- DRM_DEBUG_KMS("Unknown plane ID %d\n",
- zpos_req->plane_id);
- ret = -EINVAL;
- goto out;
- }
-
- plane = obj_to_plane(obj);
- exynos_plane = container_of(plane, struct exynos_plane, base);
-
- exynos_plane->overlay.zpos = zpos_req->zpos;
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_plane.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_plane.h
deleted file mode 100644
index 16b71f8..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_plane.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-int exynos_plane_init(struct drm_device *dev, unsigned int nr);
-int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_rotator.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_rotator.c
deleted file mode 100644
index 5bf1d6e..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_rotator.c
+++ /dev/null
@@ -1,904 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Authors: YoungJun Cho <yj44.cho@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundationr
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/pm_runtime.h>
-#include <linux/pm_qos_params.h>
-
-#include "drmP.h"
-#include "exynos_drm.h"
-#include "exynos_drm_drv.h"
-#include "exynos_drm_gem.h"
-#include "exynos_drm_iommu.h"
-
-/* Configuration */
-#define ROT_CONFIG 0x00
-#define ROT_CONFIG_IRQ (3 << 8)
-
-/* Image Control */
-#define ROT_CONTROL 0x10
-#define ROT_CONTROL_PATTERN_WRITE (1 << 16)
-#define ROT_CONTROL_FMT_YCBCR420_2P (1 << 8)
-#define ROT_CONTROL_FMT_RGB888 (6 << 8)
-#define ROT_CONTROL_FMT_MASK (7 << 8)
-#define ROT_CONTROL_FLIP_VERTICAL (2 << 6)
-#define ROT_CONTROL_FLIP_HORIZONTAL (3 << 6)
-#define ROT_CONTROL_FLIP_MASK (3 << 6)
-#define ROT_CONTROL_ROT_90 (1 << 4)
-#define ROT_CONTROL_ROT_180 (2 << 4)
-#define ROT_CONTROL_ROT_270 (3 << 4)
-#define ROT_CONTROL_ROT_MASK (3 << 4)
-#define ROT_CONTROL_START (1 << 0)
-
-/* Status */
-#define ROT_STATUS 0x20
-#define ROT_STATUS_IRQ_PENDING(x) (1 << (x))
-#define ROT_STATUS_IRQ(x) (((x) >> 8) & 0x3)
-#define ROT_STATUS_IRQ_VAL_COMPLETE 1
-#define ROT_STATUS_IRQ_VAL_ILLEGAL 2
-
-/* Sourc Buffer Address */
-#define ROT_SRC_BUF_ADDR(n) (0x30 + ((n) << 2))
-
-/* Source Buffer Size */
-#define ROT_SRC_BUF_SIZE 0x3c
-#define ROT_SRC_BUF_SIZE_H(x) ((x) << 16)
-#define ROT_SRC_BUF_SIZE_W(x) ((x) << 0)
-
-/* Source Crop Position */
-#define ROT_SRC_CROP_POS 0x40
-#define ROT_SRC_CROP_POS_Y(x) ((x) << 16)
-#define ROT_SRC_CROP_POS_X(x) ((x) << 0)
-
-/* Source Crop Size */
-#define ROT_SRC_CROP_SIZE 0x44
-#define ROT_SRC_CROP_SIZE_H(x) ((x) << 16)
-#define ROT_SRC_CROP_SIZE_W(x) ((x) << 0)
-
-/* Destination Buffer Address */
-#define ROT_DST_BUF_ADDR(n) (0x50 + ((n) << 2))
-
-/* Destination Buffer Size */
-#define ROT_DST_BUF_SIZE 0x5c
-#define ROT_DST_BUF_SIZE_H(x) ((x) << 16)
-#define ROT_DST_BUF_SIZE_W(x) ((x) << 0)
-
-/* Destination Crop Position */
-#define ROT_DST_CROP_POS 0x60
-#define ROT_DST_CROP_POS_Y(x) ((x) << 16)
-#define ROT_DST_CROP_POS_X(x) ((x) << 0)
-
-/* Round to nearest aligned value */
-#define ROT_ALIGN(x, align, mask) ((*(x) + (1 << ((align) - 1))) & (mask))
-/* Minimum limit value */
-#define ROT_MIN(min, mask) (((min) + ~(mask)) & (mask))
-/* Maximum limit value */
-#define ROT_MAX(max, mask) ((max) & (mask))
-
-enum rot_irq_status {
- ROT_IRQ_STATUS_COMPLETE = 8,
- ROT_IRQ_STATUS_ILLEGAL = 9,
-};
-
-struct rot_limit {
- u32 min_w;
- u32 min_h;
- u32 max_w;
- u32 max_h;
- u32 align;
-};
-
-struct rot_limit_table {
- struct rot_limit ycbcr420_2p;
- struct rot_limit rgb888;
-};
-
-struct rot_context {
- struct rot_limit_table *limit_tbl;
- struct clk *clock;
- struct resource *regs_res;
- void __iomem *regs;
- int irq;
- int exec_ret;
- struct exynos_drm_subdrv subdrv;
- struct completion complete;
- struct mutex exec_mutex;
- spinlock_t irq_lock;
- struct pm_qos_request_list pm_qos;
- bool suspended;
-};
-
-struct rot_buffer {
- dma_addr_t src_addr[DRM_EXYNOS_ROT_MAX_BUF];
- dma_addr_t dst_addr[DRM_EXYNOS_ROT_MAX_BUF];
- void *src_gem_obj[DRM_EXYNOS_ROT_MAX_BUF];
- void *dst_gem_obj[DRM_EXYNOS_ROT_MAX_BUF];
- u32 src_cnt;
- u32 dst_cnt;
- u32 src_w;
- u32 src_h;
- u32 dst_w;
- u32 dst_h;
-};
-
-static void rotator_reg_set_irq(struct rot_context *rot, bool enable)
-{
- u32 value = readl(rot->regs + ROT_CONFIG);
-
- if (enable == true)
- value |= ROT_CONFIG_IRQ;
- else
- value &= ~ROT_CONFIG_IRQ;
-
- writel(value, rot->regs + ROT_CONFIG);
-}
-
-static void rotator_reg_set_format(struct rot_context *rot, u32 img_fmt)
-{
- u32 value = readl(rot->regs + ROT_CONTROL);
- value &= ~ROT_CONTROL_FMT_MASK;
-
- switch (img_fmt) {
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_NV12M:
- value |= ROT_CONTROL_FMT_YCBCR420_2P;
- break;
- case DRM_FORMAT_RGB888:
- value |= ROT_CONTROL_FMT_RGB888;
- break;
- default:
- DRM_ERROR("invalid image format\n");
- return;
- }
-
- writel(value, rot->regs + ROT_CONTROL);
-}
-
-static void rotator_reg_set_flip(struct rot_context *rot,
- enum drm_exynos_rot_flip flip)
-{
- u32 value = readl(rot->regs + ROT_CONTROL);
- value &= ~ROT_CONTROL_FLIP_MASK;
-
- switch (flip) {
- case ROT_FLIP_VERTICAL:
- value |= ROT_CONTROL_FLIP_VERTICAL;
- break;
- case ROT_FLIP_HORIZONTAL:
- value |= ROT_CONTROL_FLIP_HORIZONTAL;
- break;
- default:
- /* Flip None */
- break;
- }
-
- writel(value, rot->regs + ROT_CONTROL);
-}
-
-static void rotator_reg_set_rotation(struct rot_context *rot,
- enum drm_exynos_rot_degree degree)
-{
- u32 value = readl(rot->regs + ROT_CONTROL);
- value &= ~ROT_CONTROL_ROT_MASK;
-
- switch (degree) {
- case ROT_DEGREE_90:
- value |= ROT_CONTROL_ROT_90;
- break;
- case ROT_DEGREE_180:
- value |= ROT_CONTROL_ROT_180;
- break;
- case ROT_DEGREE_270:
- value |= ROT_CONTROL_ROT_270;
- break;
- default:
- /* Rotation 0 Degree */
- break;
- }
-
- writel(value, rot->regs + ROT_CONTROL);
-}
-
-static void rotator_reg_set_start(struct rot_context *rot)
-{
- u32 value = readl(rot->regs + ROT_CONTROL);
-
- value |= ROT_CONTROL_START;
-
- writel(value, rot->regs + ROT_CONTROL);
-}
-
-static enum rot_irq_status rotator_reg_get_irq_status(struct rot_context *rot)
-{
- u32 value = readl(rot->regs + ROT_STATUS);
- value = ROT_STATUS_IRQ(value);
-
- if (value == ROT_STATUS_IRQ_VAL_COMPLETE)
- return ROT_IRQ_STATUS_COMPLETE;
- else
- return ROT_IRQ_STATUS_ILLEGAL;
-}
-
-static void rotator_reg_set_irq_status_clear(struct rot_context *rot,
- enum rot_irq_status status)
-{
- u32 value = readl(rot->regs + ROT_STATUS);
-
- value |= ROT_STATUS_IRQ_PENDING((u32)status);
-
- writel(value, rot->regs + ROT_STATUS);
-}
-
-static void rotator_reg_set_src_buf_addr(struct rot_context *rot,
- dma_addr_t addr, int i)
-{
- writel(addr, rot->regs + ROT_SRC_BUF_ADDR(i));
-}
-
-static void rotator_reg_set_src_buf_size(struct rot_context *rot, u32 w, u32 h)
-{
- u32 value = ROT_SRC_BUF_SIZE_H(h) | ROT_SRC_BUF_SIZE_W(w);
-
- writel(value, rot->regs + ROT_SRC_BUF_SIZE);
-}
-
-static void rotator_reg_set_src_crop_pos(struct rot_context *rot, u32 x, u32 y)
-{
- u32 value = ROT_SRC_CROP_POS_Y(y) | ROT_SRC_CROP_POS_X(x);
-
- writel(value, rot->regs + ROT_SRC_CROP_POS);
-}
-
-static void rotator_reg_set_src_crop_size(struct rot_context *rot, u32 w, u32 h)
-{
- u32 value = ROT_SRC_CROP_SIZE_H(h) | ROT_SRC_CROP_SIZE_W(w);
-
- writel(value, rot->regs + ROT_SRC_CROP_SIZE);
-}
-
-static void rotator_reg_set_dst_buf_addr(struct rot_context *rot,
- dma_addr_t addr, int i)
-{
- writel(addr, rot->regs + ROT_DST_BUF_ADDR(i));
-}
-
-static void rotator_reg_set_dst_buf_size(struct rot_context *rot, u32 w, u32 h)
-{
- u32 value = ROT_DST_BUF_SIZE_H(h) | ROT_DST_BUF_SIZE_W(w);
-
- writel(value, rot->regs + ROT_DST_BUF_SIZE);
-}
-
-static void rotator_reg_set_dst_crop_pos(struct rot_context *rot, u32 x, u32 y)
-{
- u32 value = ROT_DST_CROP_POS_Y(y) | ROT_DST_CROP_POS_X(x);
-
- writel(value, rot->regs + ROT_DST_CROP_POS);
-}
-
-static void rotator_reg_get_dump(struct rot_context *rot)
-{
- u32 value, i;
-
- for (i = 0; i <= ROT_DST_CROP_POS; i += 0x4) {
- value = readl(rot->regs + i);
- DRM_INFO("+0x%x: 0x%x", i, value);
- }
-}
-
-static bool rotator_check_format_n_handle_valid(u32 img_fmt,
- u32 src_buf_handle_cnt,
- u32 dst_buf_handle_cnt)
-{
- bool ret = false;
-
- if ((src_buf_handle_cnt != dst_buf_handle_cnt)
- || (src_buf_handle_cnt == 0))
- return ret;
-
- switch (img_fmt) {
- case DRM_FORMAT_NV12M:
- if (src_buf_handle_cnt == 2)
- ret = true;
- break;
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_RGB888:
- if (src_buf_handle_cnt == 1)
- ret = true;
- break;
- default:
- DRM_ERROR("invalid image format\n");
- break;
- }
-
- return ret;
-}
-
-static void rotator_align_size(struct rot_limit *limit, u32 mask, u32 *w,
- u32 *h)
-{
- u32 value;
-
- value = ROT_ALIGN(w, limit->align, mask);
- if (value < limit->min_w)
- *w = ROT_MIN(limit->min_w, mask);
- else if (value > limit->max_w)
- *w = ROT_MAX(limit->max_w, mask);
- else
- *w = value;
-
- value = ROT_ALIGN(h, limit->align, mask);
- if (value < limit->min_h)
- *h = ROT_MIN(limit->min_h, mask);
- else if (value > limit->max_h)
- *h = ROT_MAX(limit->max_h, mask);
- else
- *h = value;
-}
-
-static void rotator_align_buffer(struct rot_context *rot,
- struct rot_buffer *buf,
- struct drm_exynos_rot_buffer *req_buf,
- struct drm_exynos_rot_control *control)
-{
- struct rot_limit_table *limit_tbl = rot->limit_tbl;
- struct rot_limit *limit;
- u32 mask;
-
- /* Get size limit */
- if (control->img_fmt == DRM_FORMAT_RGB888)
- limit = &limit_tbl->rgb888;
- else
- limit = &limit_tbl->ycbcr420_2p;
-
- /* Get mask for rounding to nearest aligned value */
- mask = ~((1 << limit->align) - 1);
-
- /* For source buffer */
- buf->src_w = req_buf->src_w;
- buf->src_h = req_buf->src_h;
- rotator_align_size(limit, mask, &buf->src_w, &buf->src_h);
-
- /* For destination buffer */
- buf->dst_w = req_buf->dst_w;
- buf->dst_h = req_buf->dst_h;
- rotator_align_size(limit, mask, &buf->dst_w, &buf->dst_h);
-}
-
-static bool rotator_check_crop_boundary(struct rot_buffer *buf,
- struct drm_exynos_rot_control *control,
- struct drm_exynos_rot_crop *crop)
-{
- bool ret = true;
-
- /* Check source crop position */
- if ((crop->src_x + crop->src_w > buf->src_w)
- || (crop->src_y + crop->src_h > buf->src_h))
- return false;
-
- /* Check destination crop position */
- switch (control->degree) {
- case ROT_DEGREE_90:
- case ROT_DEGREE_270:
- if ((crop->dst_x + crop->src_h > buf->dst_w)
- || (crop->dst_y + crop->src_w > buf->dst_h))
- ret = false;
- break;
- default:
- if ((crop->dst_x + crop->src_w > buf->dst_w)
- || (crop->dst_y + crop->src_h > buf->dst_h))
- ret = false;
- break;
- }
-
- return ret;
-}
-
-static int rotator_iommu_map(struct rot_buffer *buf,
- struct drm_exynos_rot_buffer *req_buf,
- struct iommu_gem_map_params *params,
- struct list_head *iommu_list)
-{
- /* For source buffer */
- buf->src_cnt = 0;
- while (buf->src_cnt < req_buf->src_cnt) {
- buf->src_addr[buf->src_cnt] = exynos_drm_iommu_map_gem(params,
- iommu_list,
- req_buf->src_handle[buf->src_cnt],
- IOMMU_ROTATOR);
- if (!buf->src_addr[buf->src_cnt]) {
- DRM_ERROR("failed to map src handle[%u]\n",
- buf->src_cnt);
- return -EINVAL;
- }
- buf->src_gem_obj[(buf->src_cnt)++] = params->gem_obj;
- }
-
- /* For destination buffer */
- buf->dst_cnt = 0;
- while (buf->dst_cnt < req_buf->dst_cnt) {
- buf->dst_addr[buf->dst_cnt] = exynos_drm_iommu_map_gem(params,
- iommu_list,
- req_buf->dst_handle[buf->dst_cnt],
- IOMMU_ROTATOR);
- if (!buf->dst_addr[buf->dst_cnt]) {
- DRM_ERROR("failed to map dst handle[%u]\n",
- buf->dst_cnt);
- return -EINVAL;
- }
- buf->dst_gem_obj[(buf->dst_cnt)++] = params->gem_obj;
- }
-
- return 0;
-}
-
-static void rotator_iommu_unmap(struct rot_buffer *buf,
- struct iommu_gem_map_params *params)
-{
- /* For destination buffer */
- while (buf->dst_cnt > 0) {
- params->gem_obj = buf->dst_gem_obj[--(buf->dst_cnt)];
- exynos_drm_iommu_unmap_gem(params,
- buf->dst_addr[buf->dst_cnt],
- IOMMU_ROTATOR);
- }
-
- /* For source buffer */
- while (buf->src_cnt > 0) {
- params->gem_obj = buf->src_gem_obj[--(buf->src_cnt)];
- exynos_drm_iommu_unmap_gem(params,
- buf->src_addr[buf->src_cnt],
- IOMMU_ROTATOR);
- }
-}
-
-static void rotator_execute(struct rot_context *rot,
- struct rot_buffer *buf,
- struct drm_exynos_rot_control *control,
- struct drm_exynos_rot_crop *crop)
-{
- int i;
-
- pm_runtime_get_sync(rot->subdrv.dev);
-
- /* Set interrupt enable */
- rotator_reg_set_irq(rot, true);
-
- /* Set control registers */
- rotator_reg_set_format(rot, control->img_fmt);
- rotator_reg_set_flip(rot, control->flip);
- rotator_reg_set_rotation(rot, control->degree);
-
- /* Set source buffer address */
- for (i = 0; i < DRM_EXYNOS_ROT_MAX_BUF; i++)
- rotator_reg_set_src_buf_addr(rot, buf->src_addr[i], i);
-
- /* Set source buffer size */
- rotator_reg_set_src_buf_size(rot, buf->src_w, buf->src_h);
-
- /* Set destination buffer address */
- for (i = 0; i < DRM_EXYNOS_ROT_MAX_BUF; i++)
- rotator_reg_set_dst_buf_addr(rot, buf->dst_addr[i], i);
-
- /* Set destination buffer size */
- rotator_reg_set_dst_buf_size(rot, buf->dst_w, buf->dst_h);
-
- /* Set source crop image position */
- rotator_reg_set_src_crop_pos(rot, crop->src_x, crop->src_y);
-
- /* Set source crop image size */
- rotator_reg_set_src_crop_size(rot, crop->src_w, crop->src_h);
-
- /* Set destination crop image position */
- rotator_reg_set_dst_crop_pos(rot, crop->dst_x, crop->dst_y);
-
- /* Start rotator operation */
- rotator_reg_set_start(rot);
-}
-
-int exynos_drm_rotator_exec_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file)
-{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_rot_private *priv = file_priv->rot_priv;
- struct device *dev = priv->dev;
- struct rot_context *rot;
- struct drm_exynos_rot_exec_data *req = data;
- struct drm_exynos_rot_buffer *req_buf = &req->buf;
- struct drm_exynos_rot_control *control = &req->control;
- struct drm_exynos_rot_crop *crop = &req->crop;
- struct rot_buffer buf;
- struct iommu_gem_map_params params;
-
- if (!dev) {
- DRM_ERROR("failed to get dev\n");
- return -ENODEV;
- }
-
- rot = dev_get_drvdata(dev);
- if (!rot) {
- DRM_ERROR("failed to get drvdata\n");
- return -EFAULT;
- }
-
- if (rot->suspended) {
- DRM_ERROR("suspended state\n");
- return -EPERM;
- }
-
- if (!rotator_check_format_n_handle_valid(control->img_fmt,
- req_buf->src_cnt,
- req_buf->dst_cnt)) {
- DRM_ERROR("format or handles are invalid\n");
- return -EINVAL;
- }
-
- init_completion(&rot->complete);
-
- /* Align buffer */
- rotator_align_buffer(rot, &buf, req_buf, control);
-
- /* Check crop boundary */
- if (!rotator_check_crop_boundary(&buf, control, crop)) {
- DRM_ERROR("boundary errror\n");
- return -EINVAL;
- }
-
- params.dev = dev;
- params.drm_dev = drm_dev;
- params.file = file;
-
- /* Map IOMMU */
- rot->exec_ret = rotator_iommu_map(&buf, req_buf, &params,
- &priv->iommu_list);
- if (rot->exec_ret < 0)
- goto err_iommu_map;
-
- /* Assign another src/dst_addr for NV12 image format */
- if (control->img_fmt == DRM_FORMAT_NV12) {
- u32 size = crop->src_w * crop->src_h;
-
- buf.src_addr[buf.src_cnt + 1] =
- buf.src_addr[buf.src_cnt] + size;
- buf.dst_addr[buf.dst_cnt + 1] =
- buf.dst_addr[buf.dst_cnt] + size;
- }
-
- /* Execute */
- mutex_lock(&rot->exec_mutex);
- rotator_execute(rot, &buf, control, crop);
- if (!wait_for_completion_timeout(&rot->complete, 2 * HZ)) {
- DRM_ERROR("timeout error\n");
- rot->exec_ret = -ETIMEDOUT;
- mutex_unlock(&rot->exec_mutex);
- goto err_iommu_map;
- }
- mutex_unlock(&rot->exec_mutex);
-
- /* Unmap IOMMU */
- rotator_iommu_unmap(&buf, &params);
-
- return rot->exec_ret;
-
-err_iommu_map:
- rotator_iommu_unmap(&buf, &params);
- return rot->exec_ret;
-}
-EXPORT_SYMBOL_GPL(exynos_drm_rotator_exec_ioctl);
-
-static irqreturn_t rotator_irq_thread(int irq, void *arg)
-{
- struct rot_context *rot = (struct rot_context *)arg;
- enum rot_irq_status irq_status;
- unsigned long flags;
-
- pm_qos_update_request(&rot->pm_qos, 0);
-
- /* Get execution result */
- spin_lock_irqsave(&rot->irq_lock, flags);
- irq_status = rotator_reg_get_irq_status(rot);
- rotator_reg_set_irq_status_clear(rot, irq_status);
- spin_unlock_irqrestore(&rot->irq_lock, flags);
-
- rot->exec_ret = 0;
- if (irq_status != ROT_IRQ_STATUS_COMPLETE) {
- DRM_ERROR("the SFR is set illegally\n");
- rot->exec_ret = -EINVAL;
- rotator_reg_get_dump(rot);
- }
-
- pm_runtime_put(rot->subdrv.dev);
-
- complete(&rot->complete);
-
- return IRQ_HANDLED;
-}
-
-static int rotator_subdrv_open(struct drm_device *drm_dev, struct device *dev,
- struct drm_file *file)
-{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_rot_private *priv;
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(dev, "failed to allocate priv\n");
- return -ENOMEM;
- }
-
- priv->dev = dev;
- INIT_LIST_HEAD(&priv->iommu_list);
-
- file_priv->rot_priv = priv;
-
- return 0;
-}
-
-static void rotator_subdrv_close(struct drm_device *drm_dev, struct device *dev,
- struct drm_file *file)
-{
- struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_rot_private *priv = file_priv->rot_priv;
- struct iommu_gem_map_params params;
- struct iommu_info_node *node, *n;
-
- params.dev = dev;
- params.drm_dev = drm_dev;
- params.file = file;
-
- list_for_each_entry_safe(node, n, &priv->iommu_list, list) {
- params.gem_obj = node->gem_obj;
- exynos_drm_iommu_unmap_gem(&params, node->dma_addr,
- IOMMU_ROTATOR);
- list_del(&node->list);
- kfree(node);
- node = NULL;
- }
-
- kfree(priv);
-
- return;
-}
-
-static int __devinit rotator_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct rot_context *rot;
- struct resource *res;
- struct exynos_drm_subdrv *subdrv;
- int ret;
-
- rot = kzalloc(sizeof(*rot), GFP_KERNEL);
- if (!rot) {
- dev_err(dev, "failed to allocate rot\n");
- return -ENOMEM;
- }
-
- rot->limit_tbl = (struct rot_limit_table *)
- platform_get_device_id(pdev)->driver_data;
-
- mutex_init(&rot->exec_mutex);
- spin_lock_init(&rot->irq_lock);
-
- ret = exynos_drm_iommu_setup(dev);
- if (ret < 0) {
- dev_err(dev, "failed to setup iommu\n");
- goto err_iommu_setup;
- }
-
- ret = exynos_drm_iommu_activate(dev);
- if (ret < 0) {
- dev_err(dev, "failed to activate iommu\n");
- goto err_iommu_activate;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "failed to find registers\n");
- ret = -ENOENT;
- goto err_get_resource;
- }
-
- rot->regs_res = request_mem_region(res->start, resource_size(res),
- dev_name(dev));
- if (!rot->regs_res) {
- dev_err(dev, "failed to claim register region\n");
- ret = -ENOENT;
- goto err_get_resource;
- }
-
- rot->regs = ioremap(res->start, resource_size(res));
- if (!rot->regs) {
- dev_err(dev, "failed to map register\n");
- ret = -ENXIO;
- goto err_ioremap;
- }
-
- rot->irq = platform_get_irq(pdev, 0);
- if (rot->irq < 0) {
- dev_err(dev, "faild to get irq\n");
- ret = rot->irq;
- goto err_get_irq;
- }
-
- ret = request_threaded_irq(rot->irq, NULL, rotator_irq_thread,
- IRQF_ONESHOT, "drm_rotator", rot);
- if (ret < 0) {
- dev_err(dev, "failed to request irq\n");
- goto err_get_irq;
- }
-
- rot->clock = clk_get(dev, "rotator");
- if (IS_ERR_OR_NULL(rot->clock)) {
- dev_err(dev, "faild to get clock\n");
- ret = PTR_ERR(rot->clock);
- goto err_clk_get;
- }
-
- pm_runtime_enable(dev);
- pm_qos_add_request(&rot->pm_qos, PM_QOS_BUS_DMA_THROUGHPUT, 0);
-
- subdrv = &rot->subdrv;
- subdrv->dev = dev;
- subdrv->open = rotator_subdrv_open;
- subdrv->close = rotator_subdrv_close;
-
- platform_set_drvdata(pdev, rot);
-
- ret = exynos_drm_subdrv_register(subdrv);
- if (ret < 0) {
- dev_err(dev, "failed to register drm rotator device\n");
- goto err_subdrv_register;
- }
-
- dev_info(dev, "The exynos rotator is probed successfully\n");
-
- return 0;
-
-err_subdrv_register:
- pm_runtime_disable(dev);
- clk_put(rot->clock);
-err_clk_get:
- free_irq(rot->irq, rot);
-err_get_irq:
- iounmap(rot->regs);
-err_ioremap:
- release_resource(rot->regs_res);
- kfree(rot->regs_res);
-err_get_resource:
- exynos_drm_iommu_deactivate(dev);
-err_iommu_activate:
- exynos_drm_iommu_cleanup(dev);
-err_iommu_setup:
- kfree(rot);
- return ret;
-}
-
-static int __devexit rotator_remove(struct platform_device *pdev)
-{
- struct rot_context *rot = platform_get_drvdata(pdev);
-
- pm_qos_remove_request(&rot->pm_qos);
-
- exynos_drm_subdrv_unregister(&rot->subdrv);
-
- pm_runtime_disable(&pdev->dev);
- clk_put(rot->clock);
-
- free_irq(rot->irq, rot);
-
- iounmap(rot->regs);
-
- release_resource(rot->regs_res);
- kfree(rot->regs_res);
-
- exynos_drm_iommu_deactivate(&pdev->dev);
- exynos_drm_iommu_cleanup(&pdev->dev);
-
- kfree(rot);
-
- return 0;
-}
-
-struct rot_limit_table rot_limit_tbl = {
- .ycbcr420_2p = {
- .min_w = 32,
- .min_h = 32,
- .max_w = SZ_32K,
- .max_h = SZ_32K,
- .align = 3,
- },
- .rgb888 = {
- .min_w = 8,
- .min_h = 8,
- .max_w = SZ_8K,
- .max_h = SZ_8K,
- .align = 2,
- },
-};
-
-struct platform_device_id rotator_driver_ids[] = {
- {
- .name = "exynos-rot",
- .driver_data = (unsigned long)&rot_limit_tbl,
- },
- {},
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int rotator_suspend(struct device *dev)
-{
- struct rot_context *rot = dev_get_drvdata(dev);
-
- /* Check & wait for running state */
- mutex_lock(&rot->exec_mutex);
- mutex_unlock(&rot->exec_mutex);
-
- rot->suspended = true;
-
- exynos_drm_iommu_deactivate(dev);
-
- return 0;
-}
-
-static int rotator_resume(struct device *dev)
-{
- struct rot_context *rot = dev_get_drvdata(dev);
-
- rot->suspended = false;
-
- exynos_drm_iommu_activate(dev);
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int rotator_runtime_suspend(struct device *dev)
-{
- struct rot_context *rot = dev_get_drvdata(dev);
-
- clk_disable(rot->clock);
-
- return 0;
-}
-
-static int rotator_runtime_resume(struct device *dev)
-{
- struct rot_context *rot = dev_get_drvdata(dev);
-
- clk_enable(rot->clock);
- pm_qos_update_request(&rot->pm_qos, 400000);
-
- return 0;
-}
-#endif
-
-static const struct dev_pm_ops rotator_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(rotator_suspend, rotator_resume)
- SET_RUNTIME_PM_OPS(rotator_runtime_suspend, rotator_runtime_resume,
- NULL)
-};
-
-struct platform_driver rotator_driver = {
- .probe = rotator_probe,
- .remove = __devexit_p(rotator_remove),
- .id_table = rotator_driver_ids,
- .driver = {
- .name = "exynos-rot",
- .owner = THIS_MODULE,
- .pm = &rotator_pm_ops,
- },
-};
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_rotator.h b/drivers/gpu/drm/exynos_tmp/exynos_drm_rotator.h
deleted file mode 100644
index 5f383d5..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_rotator.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Authors: YoungJun Cho <yj44.cho@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundationr
- */
-
-#ifndef _EXYNOS_DRM_ROTATOR_H_
-#define _EXYNOS_DRM_ROTATOR_H_
-
-#ifdef CONFIG_DRM_EXYNOS_ROTATOR
-extern int exynos_drm_rotator_exec_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-#else
-static inline int exynos_drm_rotator_exec_ioctl(struct drm_device *dev,
- void *data,
- struct drm_file *file_priv)
-{
- return -ENOTTY;
-}
-#endif
-
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_ump.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_ump.c
deleted file mode 100644
index fd9ba2a..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_ump.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* exynos_drm_ump.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Author: Inki Dae <inki.dae@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm.h"
-
-#include <drm/exynos_drm.h>
-
-#include "exynos_drm_gem.h"
-#include "ump_kernel_interface_ref_drv.h"
-
-static unsigned int exynos_drm_ump_get_handle(unsigned int id)
-{
- return (unsigned int)ump_dd_handle_get((ump_secure_id)id);
-}
-
-static int exynos_drm_ump_add_buffer(void *obj,
- unsigned int *handle, unsigned int *id)
-{
- struct exynos_drm_gem_obj *gem_obj = obj;
- struct exynos_drm_gem_buf *buf = gem_obj->buffer;
- ump_dd_physical_block *ump_mem_desc;
- unsigned int nblocks;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (IS_NONCONTIG_BUFFER(gem_obj->flags)) {
- unsigned int i = 0;
-
- if (!buf->pages)
- return -EFAULT;
-
- nblocks = gem_obj->size >> PAGE_SHIFT;
- ump_mem_desc = kzalloc(sizeof(*ump_mem_desc) * nblocks,
- GFP_KERNEL);
- if (!ump_mem_desc) {
- DRM_ERROR("failed to alloc ump_mem_desc.\n");
- return -ENOMEM;
- }
-
- /*
- * if EXYNOS_BO_NONCONTIG type, gem object would already
- * have pages allocated by gem creation so contain page
- * frame numbers of all pages into ump descriptors.
- */
- while (i < nblocks) {
- ump_mem_desc[i].addr =
- page_to_pfn(buf->pages[i]) << PAGE_SHIFT;
- ump_mem_desc[i].size = PAGE_SIZE;
- i++;
- }
- } else {
- nblocks = 1;
-
- ump_mem_desc = kzalloc(sizeof(*ump_mem_desc), GFP_KERNEL);
- if (!ump_mem_desc) {
- DRM_ERROR("failed to alloc ump_mem_desc.\n");
- return -ENOMEM;
- }
-
- /*
- * it EXYNOS_DRM_GEM_PC type, gem would have just one
- * physically continuous buffer so let a ump descriptor
- * have one buffer address.
- */
- ump_mem_desc[0].addr = (unsigned long)buf->dma_addr;
- ump_mem_desc[0].size = buf->size;
- }
-
- /*
- * register memory information to ump descriptor table through
- * the ump descriptor data and then return ump handle to it so that
- * user can access the memory region through it.
- */
- *handle = (unsigned int)
- ump_dd_handle_create_from_phys_blocks(ump_mem_desc, nblocks);
- if (!(*handle)) {
- DRM_ERROR("failed to create ump handle.\n");
- kfree(ump_mem_desc);
- return -EINVAL;
- }
-
- *id = ump_dd_secure_id_get((ump_dd_handle)*handle);
-
- kfree(ump_mem_desc);
-
- DRM_DEBUG_KMS("ump handle : 0x%x, secure id = %d\n", *handle, *id);
- DRM_INFO("ump handle : 0x%x, secure id = %d\n", *handle, *id);
-
- return 0;
-}
-
-static void exynos_drm_ump_release_buffer(unsigned int handle)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!handle) {
- DRM_DEBUG_KMS("invalid ump handle.\n");
- return;
- }
-
- ump_dd_reference_release((ump_dd_handle)handle);
-}
-
-static struct exynos_drm_private_cb ump_callback = {
- .get_handle = exynos_drm_ump_get_handle,
- .add_buffer = exynos_drm_ump_add_buffer,
- .release_buffer = exynos_drm_ump_release_buffer,
-};
-
-static int exynos_drm_ump_init(void)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_drm_priv_cb_register(&ump_callback);
-
- return 0;
-}
-
-static void exynos_drm_ump_exit(void)
-{
-}
-
-subsys_initcall(exynos_drm_ump_init);
-module_exit(exynos_drm_ump_exit);
-
-MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC DRM UMP Backend Module");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_drm_vidi.c b/drivers/gpu/drm/exynos_tmp/exynos_drm_vidi.c
deleted file mode 100644
index 876e460..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_drm_vidi.c
+++ /dev/null
@@ -1,680 +0,0 @@
-/* exynos_drm_vidi.c
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-#include "drmP.h"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <drm/exynos_drm.h>
-
-#include "drm_edid.h"
-#include "drm_crtc_helper.h"
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_crtc.h"
-#include "exynos_drm_encoder.h"
-
-/* vidi has totally three virtual windows. */
-#define WINDOWS_NR 3
-
-#define get_vidi_context(dev) platform_get_drvdata(to_platform_device(dev))
-
-struct vidi_win_data {
- unsigned int offset_x;
- unsigned int offset_y;
- unsigned int ovl_width;
- unsigned int ovl_height;
- unsigned int fb_width;
- unsigned int fb_height;
- unsigned int bpp;
- dma_addr_t dma_addr;
- void __iomem *vaddr;
- unsigned int buf_offsize;
- unsigned int line_size; /* bytes */
- bool enabled;
-};
-
-struct vidi_context {
- struct exynos_drm_subdrv subdrv;
- struct drm_crtc *crtc;
- struct vidi_win_data win_data[WINDOWS_NR];
- struct edid *raw_edid;
- unsigned int clkdiv;
- unsigned int default_win;
- unsigned long irq_flags;
- unsigned int connected;
- bool vblank_on;
- bool suspended;
- struct work_struct work;
- struct mutex lock;
-};
-
-static const char fake_edid_info[] = {
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05,
- 0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78,
- 0x0a, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0xbd,
- 0xee, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x66, 0x21, 0x50, 0xb0, 0x51, 0x00,
- 0x1b, 0x30, 0x40, 0x70, 0x36, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e,
- 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
- 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18,
- 0x4b, 0x1a, 0x44, 0x17, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x00, 0x00, 0x00, 0xfc, 0x00, 0x53, 0x41, 0x4d, 0x53, 0x55, 0x4e, 0x47,
- 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xbc, 0x02, 0x03, 0x1e, 0xf1,
- 0x46, 0x84, 0x05, 0x03, 0x10, 0x20, 0x22, 0x23, 0x09, 0x07, 0x07, 0x83,
- 0x01, 0x00, 0x00, 0xe2, 0x00, 0x0f, 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00,
- 0xb8, 0x2d, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c,
- 0x25, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x9e, 0x8c, 0x0a, 0xd0, 0x8a,
- 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xa0, 0x5a, 0x00, 0x00,
- 0x00, 0x18, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
- 0x45, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06
-};
-
-static void vidi_fake_vblank_handler(struct work_struct *work);
-
-static bool vidi_display_is_connected(struct device *dev)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * connection request would come from user side
- * to do hotplug through specific ioctl.
- */
- return ctx->connected ? true : false;
-}
-
-static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
- u8 *edid, int len)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
- struct edid *raw_edid;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * the edid data comes from user side and it would be set
- * to ctx->raw_edid through specific ioctl.
- */
- if (!ctx->raw_edid) {
- DRM_DEBUG_KMS("raw_edid is null.\n");
- return -EFAULT;
- }
-
- raw_edid = kzalloc(len, GFP_KERNEL);
- if (!raw_edid) {
- DRM_DEBUG_KMS("failed to allocate raw_edid.\n");
- return -ENOMEM;
- }
-
- memcpy(raw_edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions)
- * EDID_LENGTH, len));
-
- /* attach the edid data to connector. */
- connector->display_info.raw_edid = (char *)raw_edid;
-
- memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions)
- * EDID_LENGTH, len));
-
- return 0;
-}
-
-static void *vidi_get_panel(struct device *dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO. */
-
- return NULL;
-}
-
-static int vidi_check_timing(struct device *dev, void *timing)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO. */
-
- return 0;
-}
-
-static int vidi_display_power_on(struct device *dev, int mode)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO */
-
- return 0;
-}
-
-static struct exynos_drm_display_ops vidi_display_ops = {
- .type = EXYNOS_DISPLAY_TYPE_VIDI,
- .is_connected = vidi_display_is_connected,
- .get_edid = vidi_get_edid,
- .get_panel = vidi_get_panel,
- .check_timing = vidi_check_timing,
- .power_on = vidi_display_power_on,
-};
-
-static void vidi_dpms(struct device *subdrv_dev, int mode)
-{
- struct vidi_context *ctx = get_vidi_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
-
- mutex_lock(&ctx->lock);
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- /* TODO. */
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- /* TODO. */
- break;
- default:
- DRM_DEBUG_KMS("unspecified mode %d\n", mode);
- break;
- }
-
- mutex_unlock(&ctx->lock);
-}
-
-static void vidi_apply(struct device *subdrv_dev)
-{
- struct vidi_context *ctx = get_vidi_context(subdrv_dev);
- struct exynos_drm_manager *mgr = ctx->subdrv.manager;
- struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
- struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
- struct vidi_win_data *win_data;
- int i;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- for (i = 0; i < WINDOWS_NR; i++) {
- win_data = &ctx->win_data[i];
- if (win_data->enabled && (ovl_ops && ovl_ops->commit))
- ovl_ops->commit(subdrv_dev, i);
- }
-
- if (mgr_ops && mgr_ops->commit)
- mgr_ops->commit(subdrv_dev);
-}
-
-static void vidi_commit(struct device *dev)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return;
-}
-
-static int vidi_enable_vblank(struct device *dev)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return -EPERM;
-
- if (!test_and_set_bit(0, &ctx->irq_flags))
- ctx->vblank_on = true;
-
- return 0;
-}
-
-static void vidi_disable_vblank(struct device *dev)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return;
-
- if (test_and_clear_bit(0, &ctx->irq_flags))
- ctx->vblank_on = false;
-}
-
-static struct exynos_drm_manager_ops vidi_manager_ops = {
- .dpms = vidi_dpms,
- .apply = vidi_apply,
- .commit = vidi_commit,
- .enable_vblank = vidi_enable_vblank,
- .disable_vblank = vidi_disable_vblank,
-};
-
-static void vidi_win_mode_set(struct device *dev,
- struct exynos_drm_overlay *overlay)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
- struct vidi_win_data *win_data;
- int win;
- unsigned long offset;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!overlay) {
- dev_err(dev, "overlay is NULL\n");
- return;
- }
-
- win = overlay->zpos;
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- offset = overlay->fb_x * (overlay->bpp >> 3);
- offset += overlay->fb_y * overlay->pitch;
-
- DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
-
- win_data = &ctx->win_data[win];
-
- win_data->offset_x = overlay->crtc_x;
- win_data->offset_y = overlay->crtc_y;
- win_data->ovl_width = overlay->crtc_width;
- win_data->ovl_height = overlay->crtc_height;
- win_data->fb_width = overlay->fb_width;
- win_data->fb_height = overlay->fb_height;
- win_data->dma_addr = overlay->dma_addr[0] + offset;
- win_data->vaddr = overlay->vaddr[0] + offset;
- win_data->bpp = overlay->bpp;
- win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
- (overlay->bpp >> 3);
- win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
-
- /*
- * some parts of win_data should be transferred to user side
- * through specific ioctl.
- */
-
- DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
- win_data->offset_x, win_data->offset_y);
- DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
- win_data->ovl_width, win_data->ovl_height);
- DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
- (unsigned long)win_data->dma_addr,
- (unsigned long)win_data->vaddr);
- DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
- overlay->fb_width, overlay->crtc_width);
-}
-
-static void vidi_win_commit(struct device *dev, int zpos)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
- struct vidi_win_data *win_data;
- int win = zpos;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (ctx->suspended)
- return;
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- win_data = &ctx->win_data[win];
-
- win_data->enabled = true;
-
- DRM_DEBUG_KMS("dma_addr = 0x%x\n", win_data->dma_addr);
-
- if (ctx->vblank_on)
- schedule_work(&ctx->work);
-}
-
-static void vidi_win_disable(struct device *dev, int zpos)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
- struct vidi_win_data *win_data;
- int win = zpos;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- win_data = &ctx->win_data[win];
- win_data->enabled = false;
-
- /* TODO. */
-}
-
-static struct exynos_drm_overlay_ops vidi_overlay_ops = {
- .mode_set = vidi_win_mode_set,
- .commit = vidi_win_commit,
- .disable = vidi_win_disable,
-};
-
-static struct exynos_drm_manager vidi_manager = {
- .pipe = -1,
- .ops = &vidi_manager_ops,
- .overlay_ops = &vidi_overlay_ops,
- .display_ops = &vidi_display_ops,
-};
-
-static void vidi_finish_pageflip(struct drm_device *drm_dev, int crtc)
-{
- struct exynos_drm_private *dev_priv = drm_dev->dev_private;
- struct drm_pending_vblank_event *e, *t;
- struct timeval now;
- unsigned long flags;
- bool is_checked = false;
-
- spin_lock_irqsave(&drm_dev->event_lock, flags);
-
- list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
- base.link) {
- /* if event's pipe isn't same as crtc then ignore it. */
- if (crtc != e->pipe)
- continue;
-
- is_checked = true;
-
- do_gettimeofday(&now);
- e->event.sequence = 0;
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
-
- list_move_tail(&e->base.link, &e->base.file_priv->event_list);
- wake_up_interruptible(&e->base.file_priv->event_wait);
- }
-
- if (is_checked) {
- /*
- * call drm_vblank_put only in case that drm_vblank_get was
- * called.
- */
- if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
- drm_vblank_put(drm_dev, crtc);
-
- /*
- * don't off vblank if vblank_disable_allowed is 1,
- * because vblank would be off by timer handler.
- */
- if (!drm_dev->vblank_disable_allowed)
- drm_vblank_off(drm_dev, crtc);
- }
-
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-}
-
-static void vidi_fake_vblank_handler(struct work_struct *work)
-{
- struct vidi_context *ctx = container_of(work, struct vidi_context,
- work);
- struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct exynos_drm_manager *manager = subdrv->manager;
-
- if (manager->pipe < 0)
- return;
-
- /* FIXME!!! */
- msleep(20);
-
- drm_handle_vblank(subdrv->drm_dev, manager->pipe);
- vidi_finish_pageflip(subdrv->drm_dev, manager->pipe);
-}
-
-static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /*
- * enable drm irq mode.
- * - with irq_enabled = 1, we can use the vblank feature.
- *
- * P.S. note that we wouldn't use drm irq handler but
- * just specific driver own one instead because
- * drm framework supports only one irq handler.
- */
- drm_dev->irq_enabled = 1;
-
- /*
- * with vblank_disable_allowed = 1, vblank interrupt will be disabled
- * by drm timer once a current process gives up ownership of
- * vblank event.(after drm_vblank_put function is called)
- */
- drm_dev->vblank_disable_allowed = 1;
-
- return 0;
-}
-
-static void vidi_subdrv_remove(struct drm_device *drm_dev)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- /* TODO. */
-}
-
-static int vidi_power_on(struct vidi_context *ctx, bool enable)
-{
- struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct device *dev = subdrv->dev;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (enable != false && enable != true)
- return -EINVAL;
-
- if (enable) {
- ctx->suspended = false;
-
- /* if vblank was enabled status, enable it again. */
- if (test_and_clear_bit(0, &ctx->irq_flags))
- vidi_enable_vblank(dev);
-
- vidi_apply(dev);
- } else {
- ctx->suspended = true;
- }
-
- return 0;
-}
-
-static int vidi_show_connection(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- int rc;
- struct vidi_context *ctx = get_vidi_context(dev);
-
- mutex_lock(&ctx->lock);
-
- rc = sprintf(buf, "%d\n", ctx->connected);
-
- mutex_unlock(&ctx->lock);
-
- return rc;
-}
-
-static int vidi_store_connection(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- ret = kstrtoint(buf, 0, &ctx->connected);
- if (ret)
- return ret;
-
- if (ctx->connected > 1)
- return -EINVAL;
-
- DRM_DEBUG_KMS("requested connection.\n");
-
- drm_helper_hpd_irq_event(ctx->subdrv.drm_dev);
-
- return len;
-}
-
-static DEVICE_ATTR(connection, 0644, vidi_show_connection,
- vidi_store_connection);
-
-int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
- struct drm_file *file_priv)
-{
- struct vidi_context *ctx = NULL;
- struct drm_encoder *encoder;
- struct exynos_drm_manager *manager;
- struct exynos_drm_display_ops *display_ops;
- struct drm_exynos_vidi_connection *vidi = data;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (!vidi) {
- DRM_DEBUG_KMS("user data for vidi is null.\n");
- return -EINVAL;
- }
-
- if (!vidi->edid) {
- DRM_DEBUG_KMS("edid data is null.\n");
- return -EINVAL;
- }
-
- if (vidi->connection > 1) {
- DRM_DEBUG_KMS("connection should be 0 or 1.\n");
- return -EINVAL;
- }
-
- list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list,
- head) {
- manager = exynos_drm_get_manager(encoder);
- display_ops = manager->display_ops;
-
- if (display_ops->type == EXYNOS_DISPLAY_TYPE_VIDI) {
- ctx = get_vidi_context(manager->dev);
- break;
- }
- }
-
- if (!ctx) {
- DRM_DEBUG_KMS("not found virtual device type encoder.\n");
- return -EINVAL;
- }
-
- if (ctx->connected == vidi->connection) {
- DRM_DEBUG_KMS("same connection request.\n");
- return -EINVAL;
- }
-
- if (vidi->connection)
- ctx->raw_edid = (struct edid *)vidi->edid;
-
- ctx->connected = vidi->connection;
- drm_helper_hpd_irq_event(ctx->subdrv.drm_dev);
-
- return 0;
-}
-
-static int __devinit vidi_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct vidi_context *ctx;
- struct exynos_drm_subdrv *subdrv;
- int ret;
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
-
- ctx->default_win = 0;
-
- INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
-
- /* for test */
- ctx->raw_edid = (struct edid *)fake_edid_info;
-
- subdrv = &ctx->subdrv;
- subdrv->dev = dev;
- subdrv->manager = &vidi_manager;
- subdrv->probe = vidi_subdrv_probe;
- subdrv->remove = vidi_subdrv_remove;
-
- mutex_init(&ctx->lock);
-
- platform_set_drvdata(pdev, ctx);
-
- ret = device_create_file(&pdev->dev, &dev_attr_connection);
- if (ret < 0)
- DRM_INFO("failed to create connection sysfs.\n");
-
- exynos_drm_subdrv_register(subdrv);
-
- return 0;
-}
-
-static int __devexit vidi_remove(struct platform_device *pdev)
-{
- struct vidi_context *ctx = platform_get_drvdata(pdev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- exynos_drm_subdrv_unregister(&ctx->subdrv);
-
- kfree(ctx);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int vidi_suspend(struct device *dev)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
-
- return vidi_power_on(ctx, false);
-}
-
-static int vidi_resume(struct device *dev)
-{
- struct vidi_context *ctx = get_vidi_context(dev);
-
- return vidi_power_on(ctx, true);
-}
-#endif
-
-static const struct dev_pm_ops vidi_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(vidi_suspend, vidi_resume)
-};
-
-struct platform_driver vidi_driver = {
- .probe = vidi_probe,
- .remove = __devexit_p(vidi_remove),
- .driver = {
- .name = "exynos-drm-vidi",
- .owner = THIS_MODULE,
- .pm = &vidi_pm_ops,
- },
-};
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_hdmi.c b/drivers/gpu/drm/exynos_tmp/exynos_hdmi.c
deleted file mode 100644
index 0c44cb7..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_hdmi.c
+++ /dev/null
@@ -1,2481 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * Based on drivers/media/video/s5p-tv/hdmi_drv.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include "drmP.h"
-#include "drm_edid.h"
-#include "drm_crtc_helper.h"
-
-#include "regs-hdmi.h"
-
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/pm_runtime.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
-
-#include <drm/exynos_drm.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_hdmi.h"
-
-#include "exynos_hdmi.h"
-
-#define MAX_WIDTH 1920
-#define MAX_HEIGHT 1080
-#define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev))
-
-struct hdmi_resources {
- struct clk *hdmi;
- struct clk *sclk_hdmi;
- struct clk *sclk_pixel;
- struct clk *sclk_hdmiphy;
- struct clk *hdmiphy;
- struct regulator_bulk_data *regul_bulk;
- int regul_count;
-};
-
-struct hdmi_context {
- struct device *dev;
- struct drm_device *drm_dev;
- bool hpd;
- bool powered;
- bool is_v13;
- bool dvi_mode;
- struct mutex hdmi_mutex;
-
- struct resource *regs_res;
- void __iomem *regs;
- unsigned int external_irq;
- unsigned int internal_irq;
-
- struct i2c_client *ddc_port;
- struct i2c_client *hdmiphy_port;
-
- /* current hdmiphy conf index */
- int cur_conf;
-
- struct hdmi_resources res;
- void *parent_ctx;
-
- void (*cfg_hpd)(bool external);
- int (*get_hpd)(void);
-};
-
-/* HDMI Version 1.3 */
-static const u8 hdmiphy_v13_conf27[32] = {
- 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
- 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
- 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
- 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
-};
-
-static const u8 hdmiphy_v13_conf27_027[32] = {
- 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
- 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
- 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
- 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
-};
-
-static const u8 hdmiphy_v13_conf74_175[32] = {
- 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
- 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
- 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
- 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
-};
-
-static const u8 hdmiphy_v13_conf74_25[32] = {
- 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
- 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
- 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
- 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
-};
-
-static const u8 hdmiphy_v13_conf148_5[32] = {
- 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
- 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
- 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
- 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
-};
-
-struct hdmi_v13_tg_regs {
- u8 cmd;
- u8 h_fsz_l;
- u8 h_fsz_h;
- u8 hact_st_l;
- u8 hact_st_h;
- u8 hact_sz_l;
- u8 hact_sz_h;
- u8 v_fsz_l;
- u8 v_fsz_h;
- u8 vsync_l;
- u8 vsync_h;
- u8 vsync2_l;
- u8 vsync2_h;
- u8 vact_st_l;
- u8 vact_st_h;
- u8 vact_sz_l;
- u8 vact_sz_h;
- u8 field_chg_l;
- u8 field_chg_h;
- u8 vact_st2_l;
- u8 vact_st2_h;
- u8 vsync_top_hdmi_l;
- u8 vsync_top_hdmi_h;
- u8 vsync_bot_hdmi_l;
- u8 vsync_bot_hdmi_h;
- u8 field_top_hdmi_l;
- u8 field_top_hdmi_h;
- u8 field_bot_hdmi_l;
- u8 field_bot_hdmi_h;
-};
-
-struct hdmi_v13_core_regs {
- u8 h_blank[2];
- u8 v_blank[3];
- u8 h_v_line[3];
- u8 vsync_pol[1];
- u8 int_pro_mode[1];
- u8 v_blank_f[3];
- u8 h_sync_gen[3];
- u8 v_sync_gen1[3];
- u8 v_sync_gen2[3];
- u8 v_sync_gen3[3];
-};
-
-struct hdmi_v13_preset_conf {
- struct hdmi_v13_core_regs core;
- struct hdmi_v13_tg_regs tg;
-};
-
-struct hdmi_v13_conf {
- int width;
- int height;
- int vrefresh;
- bool interlace;
- const u8 *hdmiphy_data;
- const struct hdmi_v13_preset_conf *conf;
-};
-
-static const struct hdmi_v13_preset_conf hdmi_v13_conf_480p = {
- .core = {
- .h_blank = {0x8a, 0x00},
- .v_blank = {0x0d, 0x6a, 0x01},
- .h_v_line = {0x0d, 0xa2, 0x35},
- .vsync_pol = {0x01},
- .int_pro_mode = {0x00},
- .v_blank_f = {0x00, 0x00, 0x00},
- .h_sync_gen = {0x0e, 0x30, 0x11},
- .v_sync_gen1 = {0x0f, 0x90, 0x00},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x5a, 0x03, /* h_fsz */
- 0x8a, 0x00, 0xd0, 0x02, /* hact */
- 0x0d, 0x02, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x2d, 0x00, 0xe0, 0x01, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x49, 0x02, /* vact_st2 */
- 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- },
-};
-
-static const struct hdmi_v13_preset_conf hdmi_v13_conf_720p60 = {
- .core = {
- .h_blank = {0x72, 0x01},
- .v_blank = {0xee, 0xf2, 0x00},
- .h_v_line = {0xee, 0x22, 0x67},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x00},
- .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
- .h_sync_gen = {0x6c, 0x50, 0x02},
- .v_sync_gen1 = {0x0a, 0x50, 0x00},
- .v_sync_gen2 = {0x01, 0x10, 0x00},
- .v_sync_gen3 = {0x01, 0x10, 0x00},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x72, 0x06, /* h_fsz */
- 0x71, 0x01, 0x01, 0x05, /* hact */
- 0xee, 0x02, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x1e, 0x00, 0xd0, 0x02, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x49, 0x02, /* vact_st2 */
- 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- },
-};
-
-static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i50 = {
- .core = {
- .h_blank = {0xd0, 0x02},
- .v_blank = {0x32, 0xB2, 0x00},
- .h_v_line = {0x65, 0x04, 0xa5},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x01},
- .v_blank_f = {0x49, 0x2A, 0x23},
- .h_sync_gen = {0x0E, 0xEA, 0x08},
- .v_sync_gen1 = {0x07, 0x20, 0x00},
- .v_sync_gen2 = {0x39, 0x42, 0x23},
- .v_sync_gen3 = {0x38, 0x87, 0x73},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x50, 0x0A, /* h_fsz */
- 0xCF, 0x02, 0x81, 0x07, /* hact */
- 0x65, 0x04, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x16, 0x00, 0x1c, 0x02, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x49, 0x02, /* vact_st2 */
- 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- },
-};
-
-static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p50 = {
- .core = {
- .h_blank = {0xd0, 0x02},
- .v_blank = {0x65, 0x6c, 0x01},
- .h_v_line = {0x65, 0x04, 0xa5},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x00},
- .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
- .h_sync_gen = {0x0e, 0xea, 0x08},
- .v_sync_gen1 = {0x09, 0x40, 0x00},
- .v_sync_gen2 = {0x01, 0x10, 0x00},
- .v_sync_gen3 = {0x01, 0x10, 0x00},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x50, 0x0A, /* h_fsz */
- 0xCF, 0x02, 0x81, 0x07, /* hact */
- 0x65, 0x04, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x2d, 0x00, 0x38, 0x04, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x48, 0x02, /* vact_st2 */
- 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- },
-};
-
-static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i60 = {
- .core = {
- .h_blank = {0x18, 0x01},
- .v_blank = {0x32, 0xB2, 0x00},
- .h_v_line = {0x65, 0x84, 0x89},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x01},
- .v_blank_f = {0x49, 0x2A, 0x23},
- .h_sync_gen = {0x56, 0x08, 0x02},
- .v_sync_gen1 = {0x07, 0x20, 0x00},
- .v_sync_gen2 = {0x39, 0x42, 0x23},
- .v_sync_gen3 = {0xa4, 0x44, 0x4a},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x98, 0x08, /* h_fsz */
- 0x17, 0x01, 0x81, 0x07, /* hact */
- 0x65, 0x04, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x16, 0x00, 0x1c, 0x02, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x49, 0x02, /* vact_st2 */
- 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- },
-};
-
-static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = {
- .core = {
- .h_blank = {0x18, 0x01},
- .v_blank = {0x65, 0x6c, 0x01},
- .h_v_line = {0x65, 0x84, 0x89},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x00},
- .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
- .h_sync_gen = {0x56, 0x08, 0x02},
- .v_sync_gen1 = {0x09, 0x40, 0x00},
- .v_sync_gen2 = {0x01, 0x10, 0x00},
- .v_sync_gen3 = {0x01, 0x10, 0x00},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x98, 0x08, /* h_fsz */
- 0x17, 0x01, 0x81, 0x07, /* hact */
- 0x65, 0x04, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x2d, 0x00, 0x38, 0x04, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x48, 0x02, /* vact_st2 */
- 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- },
-};
-
-static const struct hdmi_v13_conf hdmi_v13_confs[] = {
- { 1280, 720, 60, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 },
- { 1280, 720, 50, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 },
- { 720, 480, 60, false, hdmiphy_v13_conf27_027, &hdmi_v13_conf_480p },
- { 1920, 1080, 50, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i50 },
- { 1920, 1080, 50, false, hdmiphy_v13_conf148_5,
- &hdmi_v13_conf_1080p50 },
- { 1920, 1080, 60, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i60 },
- { 1920, 1080, 60, false, hdmiphy_v13_conf148_5,
- &hdmi_v13_conf_1080p60 },
-};
-
-/* HDMI Version 1.4 */
-static const u8 hdmiphy_conf27_027[32] = {
- 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
- 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
- 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
- 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
-};
-
-static const u8 hdmiphy_conf74_176[32] = {
- 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08,
- 0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80,
- 0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
- 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
-};
-
-static const u8 hdmiphy_conf74_25[32] = {
- 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
- 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
- 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
- 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
-};
-
-static const u8 hdmiphy_conf148_5[32] = {
- 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
- 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
- 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
- 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
-};
-
-struct hdmi_tg_regs {
- u8 cmd;
- u8 h_fsz_l;
- u8 h_fsz_h;
- u8 hact_st_l;
- u8 hact_st_h;
- u8 hact_sz_l;
- u8 hact_sz_h;
- u8 v_fsz_l;
- u8 v_fsz_h;
- u8 vsync_l;
- u8 vsync_h;
- u8 vsync2_l;
- u8 vsync2_h;
- u8 vact_st_l;
- u8 vact_st_h;
- u8 vact_sz_l;
- u8 vact_sz_h;
- u8 field_chg_l;
- u8 field_chg_h;
- u8 vact_st2_l;
- u8 vact_st2_h;
- u8 vact_st3_l;
- u8 vact_st3_h;
- u8 vact_st4_l;
- u8 vact_st4_h;
- u8 vsync_top_hdmi_l;
- u8 vsync_top_hdmi_h;
- u8 vsync_bot_hdmi_l;
- u8 vsync_bot_hdmi_h;
- u8 field_top_hdmi_l;
- u8 field_top_hdmi_h;
- u8 field_bot_hdmi_l;
- u8 field_bot_hdmi_h;
- u8 tg_3d;
-};
-
-struct hdmi_core_regs {
- u8 h_blank[2];
- u8 v2_blank[2];
- u8 v1_blank[2];
- u8 v_line[2];
- u8 h_line[2];
- u8 hsync_pol[1];
- u8 vsync_pol[1];
- u8 int_pro_mode[1];
- u8 v_blank_f0[2];
- u8 v_blank_f1[2];
- u8 h_sync_start[2];
- u8 h_sync_end[2];
- u8 v_sync_line_bef_2[2];
- u8 v_sync_line_bef_1[2];
- u8 v_sync_line_aft_2[2];
- u8 v_sync_line_aft_1[2];
- u8 v_sync_line_aft_pxl_2[2];
- u8 v_sync_line_aft_pxl_1[2];
- u8 v_blank_f2[2]; /* for 3D mode */
- u8 v_blank_f3[2]; /* for 3D mode */
- u8 v_blank_f4[2]; /* for 3D mode */
- u8 v_blank_f5[2]; /* for 3D mode */
- u8 v_sync_line_aft_3[2];
- u8 v_sync_line_aft_4[2];
- u8 v_sync_line_aft_5[2];
- u8 v_sync_line_aft_6[2];
- u8 v_sync_line_aft_pxl_3[2];
- u8 v_sync_line_aft_pxl_4[2];
- u8 v_sync_line_aft_pxl_5[2];
- u8 v_sync_line_aft_pxl_6[2];
- u8 vact_space_1[2];
- u8 vact_space_2[2];
- u8 vact_space_3[2];
- u8 vact_space_4[2];
- u8 vact_space_5[2];
- u8 vact_space_6[2];
-};
-
-struct hdmi_preset_conf {
- struct hdmi_core_regs core;
- struct hdmi_tg_regs tg;
-};
-
-struct hdmi_conf {
- int width;
- int height;
- int vrefresh;
- bool interlace;
- const u8 *hdmiphy_data;
- const struct hdmi_preset_conf *conf;
-};
-
-static const struct hdmi_preset_conf hdmi_conf_480p60 = {
- .core = {
- .h_blank = {0x8a, 0x00},
- .v2_blank = {0x0d, 0x02},
- .v1_blank = {0x2d, 0x00},
- .v_line = {0x0d, 0x02},
- .h_line = {0x5a, 0x03},
- .hsync_pol = {0x01},
- .vsync_pol = {0x01},
- .int_pro_mode = {0x00},
- .v_blank_f0 = {0xff, 0xff},
- .v_blank_f1 = {0xff, 0xff},
- .h_sync_start = {0x0e, 0x00},
- .h_sync_end = {0x4c, 0x00},
- .v_sync_line_bef_2 = {0x0f, 0x00},
- .v_sync_line_bef_1 = {0x09, 0x00},
- .v_sync_line_aft_2 = {0xff, 0xff},
- .v_sync_line_aft_1 = {0xff, 0xff},
- .v_sync_line_aft_pxl_2 = {0xff, 0xff},
- .v_sync_line_aft_pxl_1 = {0xff, 0xff},
- .v_blank_f2 = {0xff, 0xff},
- .v_blank_f3 = {0xff, 0xff},
- .v_blank_f4 = {0xff, 0xff},
- .v_blank_f5 = {0xff, 0xff},
- .v_sync_line_aft_3 = {0xff, 0xff},
- .v_sync_line_aft_4 = {0xff, 0xff},
- .v_sync_line_aft_5 = {0xff, 0xff},
- .v_sync_line_aft_6 = {0xff, 0xff},
- .v_sync_line_aft_pxl_3 = {0xff, 0xff},
- .v_sync_line_aft_pxl_4 = {0xff, 0xff},
- .v_sync_line_aft_pxl_5 = {0xff, 0xff},
- .v_sync_line_aft_pxl_6 = {0xff, 0xff},
- .vact_space_1 = {0xff, 0xff},
- .vact_space_2 = {0xff, 0xff},
- .vact_space_3 = {0xff, 0xff},
- .vact_space_4 = {0xff, 0xff},
- .vact_space_5 = {0xff, 0xff},
- .vact_space_6 = {0xff, 0xff},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x5a, 0x03, /* h_fsz */
- 0x8a, 0x00, 0xd0, 0x02, /* hact */
- 0x0d, 0x02, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x2d, 0x00, 0xe0, 0x01, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x48, 0x02, /* vact_st2 */
- 0x00, 0x00, /* vact_st3 */
- 0x00, 0x00, /* vact_st4 */
- 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- 0x00, /* 3d FP */
- },
-};
-
-static const struct hdmi_preset_conf hdmi_conf_720p50 = {
- .core = {
- .h_blank = {0xbc, 0x02},
- .v2_blank = {0xee, 0x02},
- .v1_blank = {0x1e, 0x00},
- .v_line = {0xee, 0x02},
- .h_line = {0xbc, 0x07},
- .hsync_pol = {0x00},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x00},
- .v_blank_f0 = {0xff, 0xff},
- .v_blank_f1 = {0xff, 0xff},
- .h_sync_start = {0xb6, 0x01},
- .h_sync_end = {0xde, 0x01},
- .v_sync_line_bef_2 = {0x0a, 0x00},
- .v_sync_line_bef_1 = {0x05, 0x00},
- .v_sync_line_aft_2 = {0xff, 0xff},
- .v_sync_line_aft_1 = {0xff, 0xff},
- .v_sync_line_aft_pxl_2 = {0xff, 0xff},
- .v_sync_line_aft_pxl_1 = {0xff, 0xff},
- .v_blank_f2 = {0xff, 0xff},
- .v_blank_f3 = {0xff, 0xff},
- .v_blank_f4 = {0xff, 0xff},
- .v_blank_f5 = {0xff, 0xff},
- .v_sync_line_aft_3 = {0xff, 0xff},
- .v_sync_line_aft_4 = {0xff, 0xff},
- .v_sync_line_aft_5 = {0xff, 0xff},
- .v_sync_line_aft_6 = {0xff, 0xff},
- .v_sync_line_aft_pxl_3 = {0xff, 0xff},
- .v_sync_line_aft_pxl_4 = {0xff, 0xff},
- .v_sync_line_aft_pxl_5 = {0xff, 0xff},
- .v_sync_line_aft_pxl_6 = {0xff, 0xff},
- .vact_space_1 = {0xff, 0xff},
- .vact_space_2 = {0xff, 0xff},
- .vact_space_3 = {0xff, 0xff},
- .vact_space_4 = {0xff, 0xff},
- .vact_space_5 = {0xff, 0xff},
- .vact_space_6 = {0xff, 0xff},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0xbc, 0x07, /* h_fsz */
- 0xbc, 0x02, 0x00, 0x05, /* hact */
- 0xee, 0x02, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x1e, 0x00, 0xd0, 0x02, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x48, 0x02, /* vact_st2 */
- 0x00, 0x00, /* vact_st3 */
- 0x00, 0x00, /* vact_st4 */
- 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- 0x00, /* 3d FP */
- },
-};
-
-static const struct hdmi_preset_conf hdmi_conf_720p60 = {
- .core = {
- .h_blank = {0x72, 0x01},
- .v2_blank = {0xee, 0x02},
- .v1_blank = {0x1e, 0x00},
- .v_line = {0xee, 0x02},
- .h_line = {0x72, 0x06},
- .hsync_pol = {0x00},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x00},
- .v_blank_f0 = {0xff, 0xff},
- .v_blank_f1 = {0xff, 0xff},
- .h_sync_start = {0x6c, 0x00},
- .h_sync_end = {0x94, 0x00},
- .v_sync_line_bef_2 = {0x0a, 0x00},
- .v_sync_line_bef_1 = {0x05, 0x00},
- .v_sync_line_aft_2 = {0xff, 0xff},
- .v_sync_line_aft_1 = {0xff, 0xff},
- .v_sync_line_aft_pxl_2 = {0xff, 0xff},
- .v_sync_line_aft_pxl_1 = {0xff, 0xff},
- .v_blank_f2 = {0xff, 0xff},
- .v_blank_f3 = {0xff, 0xff},
- .v_blank_f4 = {0xff, 0xff},
- .v_blank_f5 = {0xff, 0xff},
- .v_sync_line_aft_3 = {0xff, 0xff},
- .v_sync_line_aft_4 = {0xff, 0xff},
- .v_sync_line_aft_5 = {0xff, 0xff},
- .v_sync_line_aft_6 = {0xff, 0xff},
- .v_sync_line_aft_pxl_3 = {0xff, 0xff},
- .v_sync_line_aft_pxl_4 = {0xff, 0xff},
- .v_sync_line_aft_pxl_5 = {0xff, 0xff},
- .v_sync_line_aft_pxl_6 = {0xff, 0xff},
- .vact_space_1 = {0xff, 0xff},
- .vact_space_2 = {0xff, 0xff},
- .vact_space_3 = {0xff, 0xff},
- .vact_space_4 = {0xff, 0xff},
- .vact_space_5 = {0xff, 0xff},
- .vact_space_6 = {0xff, 0xff},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x72, 0x06, /* h_fsz */
- 0x72, 0x01, 0x00, 0x05, /* hact */
- 0xee, 0x02, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x1e, 0x00, 0xd0, 0x02, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x48, 0x02, /* vact_st2 */
- 0x00, 0x00, /* vact_st3 */
- 0x00, 0x00, /* vact_st4 */
- 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- 0x00, /* 3d FP */
- },
-};
-
-static const struct hdmi_preset_conf hdmi_conf_1080i50 = {
- .core = {
- .h_blank = {0xd0, 0x02},
- .v2_blank = {0x32, 0x02},
- .v1_blank = {0x16, 0x00},
- .v_line = {0x65, 0x04},
- .h_line = {0x50, 0x0a},
- .hsync_pol = {0x00},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x01},
- .v_blank_f0 = {0x49, 0x02},
- .v_blank_f1 = {0x65, 0x04},
- .h_sync_start = {0x0e, 0x02},
- .h_sync_end = {0x3a, 0x02},
- .v_sync_line_bef_2 = {0x07, 0x00},
- .v_sync_line_bef_1 = {0x02, 0x00},
- .v_sync_line_aft_2 = {0x39, 0x02},
- .v_sync_line_aft_1 = {0x34, 0x02},
- .v_sync_line_aft_pxl_2 = {0x38, 0x07},
- .v_sync_line_aft_pxl_1 = {0x38, 0x07},
- .v_blank_f2 = {0xff, 0xff},
- .v_blank_f3 = {0xff, 0xff},
- .v_blank_f4 = {0xff, 0xff},
- .v_blank_f5 = {0xff, 0xff},
- .v_sync_line_aft_3 = {0xff, 0xff},
- .v_sync_line_aft_4 = {0xff, 0xff},
- .v_sync_line_aft_5 = {0xff, 0xff},
- .v_sync_line_aft_6 = {0xff, 0xff},
- .v_sync_line_aft_pxl_3 = {0xff, 0xff},
- .v_sync_line_aft_pxl_4 = {0xff, 0xff},
- .v_sync_line_aft_pxl_5 = {0xff, 0xff},
- .v_sync_line_aft_pxl_6 = {0xff, 0xff},
- .vact_space_1 = {0xff, 0xff},
- .vact_space_2 = {0xff, 0xff},
- .vact_space_3 = {0xff, 0xff},
- .vact_space_4 = {0xff, 0xff},
- .vact_space_5 = {0xff, 0xff},
- .vact_space_6 = {0xff, 0xff},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x50, 0x0a, /* h_fsz */
- 0xd0, 0x02, 0x80, 0x07, /* hact */
- 0x65, 0x04, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x16, 0x00, 0x1c, 0x02, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x49, 0x02, /* vact_st2 */
- 0x00, 0x00, /* vact_st3 */
- 0x00, 0x00, /* vact_st4 */
- 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- 0x00, /* 3d FP */
- },
-};
-
-static const struct hdmi_preset_conf hdmi_conf_1080i60 = {
- .core = {
- .h_blank = {0x18, 0x01},
- .v2_blank = {0x32, 0x02},
- .v1_blank = {0x16, 0x00},
- .v_line = {0x65, 0x04},
- .h_line = {0x98, 0x08},
- .hsync_pol = {0x00},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x01},
- .v_blank_f0 = {0x49, 0x02},
- .v_blank_f1 = {0x65, 0x04},
- .h_sync_start = {0x56, 0x00},
- .h_sync_end = {0x82, 0x00},
- .v_sync_line_bef_2 = {0x07, 0x00},
- .v_sync_line_bef_1 = {0x02, 0x00},
- .v_sync_line_aft_2 = {0x39, 0x02},
- .v_sync_line_aft_1 = {0x34, 0x02},
- .v_sync_line_aft_pxl_2 = {0xa4, 0x04},
- .v_sync_line_aft_pxl_1 = {0xa4, 0x04},
- .v_blank_f2 = {0xff, 0xff},
- .v_blank_f3 = {0xff, 0xff},
- .v_blank_f4 = {0xff, 0xff},
- .v_blank_f5 = {0xff, 0xff},
- .v_sync_line_aft_3 = {0xff, 0xff},
- .v_sync_line_aft_4 = {0xff, 0xff},
- .v_sync_line_aft_5 = {0xff, 0xff},
- .v_sync_line_aft_6 = {0xff, 0xff},
- .v_sync_line_aft_pxl_3 = {0xff, 0xff},
- .v_sync_line_aft_pxl_4 = {0xff, 0xff},
- .v_sync_line_aft_pxl_5 = {0xff, 0xff},
- .v_sync_line_aft_pxl_6 = {0xff, 0xff},
- .vact_space_1 = {0xff, 0xff},
- .vact_space_2 = {0xff, 0xff},
- .vact_space_3 = {0xff, 0xff},
- .vact_space_4 = {0xff, 0xff},
- .vact_space_5 = {0xff, 0xff},
- .vact_space_6 = {0xff, 0xff},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x98, 0x08, /* h_fsz */
- 0x18, 0x01, 0x80, 0x07, /* hact */
- 0x65, 0x04, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x16, 0x00, 0x1c, 0x02, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x49, 0x02, /* vact_st2 */
- 0x00, 0x00, /* vact_st3 */
- 0x00, 0x00, /* vact_st4 */
- 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- 0x00, /* 3d FP */
- },
-};
-
-static const struct hdmi_preset_conf hdmi_conf_1080p30 = {
- .core = {
- .h_blank = {0x18, 0x01},
- .v2_blank = {0x65, 0x04},
- .v1_blank = {0x2d, 0x00},
- .v_line = {0x65, 0x04},
- .h_line = {0x98, 0x08},
- .hsync_pol = {0x00},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x00},
- .v_blank_f0 = {0xff, 0xff},
- .v_blank_f1 = {0xff, 0xff},
- .h_sync_start = {0x56, 0x00},
- .h_sync_end = {0x82, 0x00},
- .v_sync_line_bef_2 = {0x09, 0x00},
- .v_sync_line_bef_1 = {0x04, 0x00},
- .v_sync_line_aft_2 = {0xff, 0xff},
- .v_sync_line_aft_1 = {0xff, 0xff},
- .v_sync_line_aft_pxl_2 = {0xff, 0xff},
- .v_sync_line_aft_pxl_1 = {0xff, 0xff},
- .v_blank_f2 = {0xff, 0xff},
- .v_blank_f3 = {0xff, 0xff},
- .v_blank_f4 = {0xff, 0xff},
- .v_blank_f5 = {0xff, 0xff},
- .v_sync_line_aft_3 = {0xff, 0xff},
- .v_sync_line_aft_4 = {0xff, 0xff},
- .v_sync_line_aft_5 = {0xff, 0xff},
- .v_sync_line_aft_6 = {0xff, 0xff},
- .v_sync_line_aft_pxl_3 = {0xff, 0xff},
- .v_sync_line_aft_pxl_4 = {0xff, 0xff},
- .v_sync_line_aft_pxl_5 = {0xff, 0xff},
- .v_sync_line_aft_pxl_6 = {0xff, 0xff},
- .vact_space_1 = {0xff, 0xff},
- .vact_space_2 = {0xff, 0xff},
- .vact_space_3 = {0xff, 0xff},
- .vact_space_4 = {0xff, 0xff},
- .vact_space_5 = {0xff, 0xff},
- .vact_space_6 = {0xff, 0xff},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x98, 0x08, /* h_fsz */
- 0x18, 0x01, 0x80, 0x07, /* hact */
- 0x65, 0x04, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x2d, 0x00, 0x38, 0x04, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x48, 0x02, /* vact_st2 */
- 0x00, 0x00, /* vact_st3 */
- 0x00, 0x00, /* vact_st4 */
- 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- 0x00, /* 3d FP */
- },
-};
-
-static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
- .core = {
- .h_blank = {0xd0, 0x02},
- .v2_blank = {0x65, 0x04},
- .v1_blank = {0x2d, 0x00},
- .v_line = {0x65, 0x04},
- .h_line = {0x50, 0x0a},
- .hsync_pol = {0x00},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x00},
- .v_blank_f0 = {0xff, 0xff},
- .v_blank_f1 = {0xff, 0xff},
- .h_sync_start = {0x0e, 0x02},
- .h_sync_end = {0x3a, 0x02},
- .v_sync_line_bef_2 = {0x09, 0x00},
- .v_sync_line_bef_1 = {0x04, 0x00},
- .v_sync_line_aft_2 = {0xff, 0xff},
- .v_sync_line_aft_1 = {0xff, 0xff},
- .v_sync_line_aft_pxl_2 = {0xff, 0xff},
- .v_sync_line_aft_pxl_1 = {0xff, 0xff},
- .v_blank_f2 = {0xff, 0xff},
- .v_blank_f3 = {0xff, 0xff},
- .v_blank_f4 = {0xff, 0xff},
- .v_blank_f5 = {0xff, 0xff},
- .v_sync_line_aft_3 = {0xff, 0xff},
- .v_sync_line_aft_4 = {0xff, 0xff},
- .v_sync_line_aft_5 = {0xff, 0xff},
- .v_sync_line_aft_6 = {0xff, 0xff},
- .v_sync_line_aft_pxl_3 = {0xff, 0xff},
- .v_sync_line_aft_pxl_4 = {0xff, 0xff},
- .v_sync_line_aft_pxl_5 = {0xff, 0xff},
- .v_sync_line_aft_pxl_6 = {0xff, 0xff},
- .vact_space_1 = {0xff, 0xff},
- .vact_space_2 = {0xff, 0xff},
- .vact_space_3 = {0xff, 0xff},
- .vact_space_4 = {0xff, 0xff},
- .vact_space_5 = {0xff, 0xff},
- .vact_space_6 = {0xff, 0xff},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x50, 0x0a, /* h_fsz */
- 0xd0, 0x02, 0x80, 0x07, /* hact */
- 0x65, 0x04, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x2d, 0x00, 0x38, 0x04, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x48, 0x02, /* vact_st2 */
- 0x00, 0x00, /* vact_st3 */
- 0x00, 0x00, /* vact_st4 */
- 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- 0x00, /* 3d FP */
- },
-};
-
-static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
- .core = {
- .h_blank = {0x18, 0x01},
- .v2_blank = {0x65, 0x04},
- .v1_blank = {0x2d, 0x00},
- .v_line = {0x65, 0x04},
- .h_line = {0x98, 0x08},
- .hsync_pol = {0x00},
- .vsync_pol = {0x00},
- .int_pro_mode = {0x00},
- .v_blank_f0 = {0xff, 0xff},
- .v_blank_f1 = {0xff, 0xff},
- .h_sync_start = {0x56, 0x00},
- .h_sync_end = {0x82, 0x00},
- .v_sync_line_bef_2 = {0x09, 0x00},
- .v_sync_line_bef_1 = {0x04, 0x00},
- .v_sync_line_aft_2 = {0xff, 0xff},
- .v_sync_line_aft_1 = {0xff, 0xff},
- .v_sync_line_aft_pxl_2 = {0xff, 0xff},
- .v_sync_line_aft_pxl_1 = {0xff, 0xff},
- .v_blank_f2 = {0xff, 0xff},
- .v_blank_f3 = {0xff, 0xff},
- .v_blank_f4 = {0xff, 0xff},
- .v_blank_f5 = {0xff, 0xff},
- .v_sync_line_aft_3 = {0xff, 0xff},
- .v_sync_line_aft_4 = {0xff, 0xff},
- .v_sync_line_aft_5 = {0xff, 0xff},
- .v_sync_line_aft_6 = {0xff, 0xff},
- .v_sync_line_aft_pxl_3 = {0xff, 0xff},
- .v_sync_line_aft_pxl_4 = {0xff, 0xff},
- .v_sync_line_aft_pxl_5 = {0xff, 0xff},
- .v_sync_line_aft_pxl_6 = {0xff, 0xff},
- /* other don't care */
- },
- .tg = {
- 0x00, /* cmd */
- 0x98, 0x08, /* h_fsz */
- 0x18, 0x01, 0x80, 0x07, /* hact */
- 0x65, 0x04, /* v_fsz */
- 0x01, 0x00, 0x33, 0x02, /* vsync */
- 0x2d, 0x00, 0x38, 0x04, /* vact */
- 0x33, 0x02, /* field_chg */
- 0x48, 0x02, /* vact_st2 */
- 0x00, 0x00, /* vact_st3 */
- 0x00, 0x00, /* vact_st4 */
- 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
- 0x01, 0x00, 0x33, 0x02, /* field top/bot */
- 0x00, /* 3d FP */
- },
-};
-
-static const struct hdmi_conf hdmi_confs[] = {
- { 720, 480, 60, false, hdmiphy_conf27_027, &hdmi_conf_480p60 },
- { 1280, 720, 50, false, hdmiphy_conf74_25, &hdmi_conf_720p50 },
- { 1280, 720, 60, false, hdmiphy_conf74_25, &hdmi_conf_720p60 },
- { 1920, 1080, 50, true, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
- { 1920, 1080, 60, true, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
- { 1920, 1080, 30, false, hdmiphy_conf74_176, &hdmi_conf_1080p30 },
-};
-
-
-static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
-{
- return readl(hdata->regs + reg_id);
-}
-
-static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
- u32 reg_id, u8 value)
-{
- writeb(value, hdata->regs + reg_id);
-}
-
-static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
- u32 reg_id, u32 value, u32 mask)
-{
- u32 old = readl(hdata->regs + reg_id);
- value = (value & mask) | (old & ~mask);
- writel(value, hdata->regs + reg_id);
-}
-
-static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
-{
-#define DUMPREG(reg_id) \
- DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
- readl(hdata->regs + reg_id))
- DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
- DUMPREG(HDMI_INTC_FLAG);
- DUMPREG(HDMI_INTC_CON);
- DUMPREG(HDMI_HPD_STATUS);
- DUMPREG(HDMI_V13_PHY_RSTOUT);
- DUMPREG(HDMI_V13_PHY_VPLL);
- DUMPREG(HDMI_V13_PHY_CMU);
- DUMPREG(HDMI_V13_CORE_RSTOUT);
-
- DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
- DUMPREG(HDMI_CON_0);
- DUMPREG(HDMI_CON_1);
- DUMPREG(HDMI_CON_2);
- DUMPREG(HDMI_SYS_STATUS);
- DUMPREG(HDMI_V13_PHY_STATUS);
- DUMPREG(HDMI_STATUS_EN);
- DUMPREG(HDMI_HPD);
- DUMPREG(HDMI_MODE_SEL);
- DUMPREG(HDMI_V13_HPD_GEN);
- DUMPREG(HDMI_V13_DC_CONTROL);
- DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
-
- DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
- DUMPREG(HDMI_H_BLANK_0);
- DUMPREG(HDMI_H_BLANK_1);
- DUMPREG(HDMI_V13_V_BLANK_0);
- DUMPREG(HDMI_V13_V_BLANK_1);
- DUMPREG(HDMI_V13_V_BLANK_2);
- DUMPREG(HDMI_V13_H_V_LINE_0);
- DUMPREG(HDMI_V13_H_V_LINE_1);
- DUMPREG(HDMI_V13_H_V_LINE_2);
- DUMPREG(HDMI_VSYNC_POL);
- DUMPREG(HDMI_INT_PRO_MODE);
- DUMPREG(HDMI_V13_V_BLANK_F_0);
- DUMPREG(HDMI_V13_V_BLANK_F_1);
- DUMPREG(HDMI_V13_V_BLANK_F_2);
- DUMPREG(HDMI_V13_H_SYNC_GEN_0);
- DUMPREG(HDMI_V13_H_SYNC_GEN_1);
- DUMPREG(HDMI_V13_H_SYNC_GEN_2);
- DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
- DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
- DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
- DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
- DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
- DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
- DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
- DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
- DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
-
- DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
- DUMPREG(HDMI_TG_CMD);
- DUMPREG(HDMI_TG_H_FSZ_L);
- DUMPREG(HDMI_TG_H_FSZ_H);
- DUMPREG(HDMI_TG_HACT_ST_L);
- DUMPREG(HDMI_TG_HACT_ST_H);
- DUMPREG(HDMI_TG_HACT_SZ_L);
- DUMPREG(HDMI_TG_HACT_SZ_H);
- DUMPREG(HDMI_TG_V_FSZ_L);
- DUMPREG(HDMI_TG_V_FSZ_H);
- DUMPREG(HDMI_TG_VSYNC_L);
- DUMPREG(HDMI_TG_VSYNC_H);
- DUMPREG(HDMI_TG_VSYNC2_L);
- DUMPREG(HDMI_TG_VSYNC2_H);
- DUMPREG(HDMI_TG_VACT_ST_L);
- DUMPREG(HDMI_TG_VACT_ST_H);
- DUMPREG(HDMI_TG_VACT_SZ_L);
- DUMPREG(HDMI_TG_VACT_SZ_H);
- DUMPREG(HDMI_TG_FIELD_CHG_L);
- DUMPREG(HDMI_TG_FIELD_CHG_H);
- DUMPREG(HDMI_TG_VACT_ST2_L);
- DUMPREG(HDMI_TG_VACT_ST2_H);
- DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
- DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
- DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
- DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
- DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
- DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
- DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
- DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
-#undef DUMPREG
-}
-
-static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
-{
- int i;
-
-#define DUMPREG(reg_id) \
- DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
- readl(hdata->regs + reg_id))
-
- DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
- DUMPREG(HDMI_INTC_CON);
- DUMPREG(HDMI_INTC_FLAG);
- DUMPREG(HDMI_HPD_STATUS);
- DUMPREG(HDMI_INTC_CON_1);
- DUMPREG(HDMI_INTC_FLAG_1);
- DUMPREG(HDMI_PHY_STATUS_0);
- DUMPREG(HDMI_PHY_STATUS_PLL);
- DUMPREG(HDMI_PHY_CON_0);
- DUMPREG(HDMI_PHY_RSTOUT);
- DUMPREG(HDMI_PHY_VPLL);
- DUMPREG(HDMI_PHY_CMU);
- DUMPREG(HDMI_CORE_RSTOUT);
-
- DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
- DUMPREG(HDMI_CON_0);
- DUMPREG(HDMI_CON_1);
- DUMPREG(HDMI_CON_2);
- DUMPREG(HDMI_SYS_STATUS);
- DUMPREG(HDMI_PHY_STATUS_0);
- DUMPREG(HDMI_STATUS_EN);
- DUMPREG(HDMI_HPD);
- DUMPREG(HDMI_MODE_SEL);
- DUMPREG(HDMI_ENC_EN);
- DUMPREG(HDMI_DC_CONTROL);
- DUMPREG(HDMI_VIDEO_PATTERN_GEN);
-
- DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
- DUMPREG(HDMI_H_BLANK_0);
- DUMPREG(HDMI_H_BLANK_1);
- DUMPREG(HDMI_V2_BLANK_0);
- DUMPREG(HDMI_V2_BLANK_1);
- DUMPREG(HDMI_V1_BLANK_0);
- DUMPREG(HDMI_V1_BLANK_1);
- DUMPREG(HDMI_V_LINE_0);
- DUMPREG(HDMI_V_LINE_1);
- DUMPREG(HDMI_H_LINE_0);
- DUMPREG(HDMI_H_LINE_1);
- DUMPREG(HDMI_HSYNC_POL);
-
- DUMPREG(HDMI_VSYNC_POL);
- DUMPREG(HDMI_INT_PRO_MODE);
- DUMPREG(HDMI_V_BLANK_F0_0);
- DUMPREG(HDMI_V_BLANK_F0_1);
- DUMPREG(HDMI_V_BLANK_F1_0);
- DUMPREG(HDMI_V_BLANK_F1_1);
-
- DUMPREG(HDMI_H_SYNC_START_0);
- DUMPREG(HDMI_H_SYNC_START_1);
- DUMPREG(HDMI_H_SYNC_END_0);
- DUMPREG(HDMI_H_SYNC_END_1);
-
- DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
- DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
- DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
- DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
-
- DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
-
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
-
- DUMPREG(HDMI_V_BLANK_F2_0);
- DUMPREG(HDMI_V_BLANK_F2_1);
- DUMPREG(HDMI_V_BLANK_F3_0);
- DUMPREG(HDMI_V_BLANK_F3_1);
- DUMPREG(HDMI_V_BLANK_F4_0);
- DUMPREG(HDMI_V_BLANK_F4_1);
- DUMPREG(HDMI_V_BLANK_F5_0);
- DUMPREG(HDMI_V_BLANK_F5_1);
-
- DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
-
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
- DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
-
- DUMPREG(HDMI_VACT_SPACE_1_0);
- DUMPREG(HDMI_VACT_SPACE_1_1);
- DUMPREG(HDMI_VACT_SPACE_2_0);
- DUMPREG(HDMI_VACT_SPACE_2_1);
- DUMPREG(HDMI_VACT_SPACE_3_0);
- DUMPREG(HDMI_VACT_SPACE_3_1);
- DUMPREG(HDMI_VACT_SPACE_4_0);
- DUMPREG(HDMI_VACT_SPACE_4_1);
- DUMPREG(HDMI_VACT_SPACE_5_0);
- DUMPREG(HDMI_VACT_SPACE_5_1);
- DUMPREG(HDMI_VACT_SPACE_6_0);
- DUMPREG(HDMI_VACT_SPACE_6_1);
-
- DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
- DUMPREG(HDMI_TG_CMD);
- DUMPREG(HDMI_TG_H_FSZ_L);
- DUMPREG(HDMI_TG_H_FSZ_H);
- DUMPREG(HDMI_TG_HACT_ST_L);
- DUMPREG(HDMI_TG_HACT_ST_H);
- DUMPREG(HDMI_TG_HACT_SZ_L);
- DUMPREG(HDMI_TG_HACT_SZ_H);
- DUMPREG(HDMI_TG_V_FSZ_L);
- DUMPREG(HDMI_TG_V_FSZ_H);
- DUMPREG(HDMI_TG_VSYNC_L);
- DUMPREG(HDMI_TG_VSYNC_H);
- DUMPREG(HDMI_TG_VSYNC2_L);
- DUMPREG(HDMI_TG_VSYNC2_H);
- DUMPREG(HDMI_TG_VACT_ST_L);
- DUMPREG(HDMI_TG_VACT_ST_H);
- DUMPREG(HDMI_TG_VACT_SZ_L);
- DUMPREG(HDMI_TG_VACT_SZ_H);
- DUMPREG(HDMI_TG_FIELD_CHG_L);
- DUMPREG(HDMI_TG_FIELD_CHG_H);
- DUMPREG(HDMI_TG_VACT_ST2_L);
- DUMPREG(HDMI_TG_VACT_ST2_H);
- DUMPREG(HDMI_TG_VACT_ST3_L);
- DUMPREG(HDMI_TG_VACT_ST3_H);
- DUMPREG(HDMI_TG_VACT_ST4_L);
- DUMPREG(HDMI_TG_VACT_ST4_H);
- DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
- DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
- DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
- DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
- DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
- DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
- DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
- DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
- DUMPREG(HDMI_TG_3D);
-
- DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
- DUMPREG(HDMI_AVI_CON);
- DUMPREG(HDMI_AVI_HEADER0);
- DUMPREG(HDMI_AVI_HEADER1);
- DUMPREG(HDMI_AVI_HEADER2);
- DUMPREG(HDMI_AVI_CHECK_SUM);
- DUMPREG(HDMI_VSI_CON);
- DUMPREG(HDMI_VSI_HEADER0);
- DUMPREG(HDMI_VSI_HEADER1);
- DUMPREG(HDMI_VSI_HEADER2);
- for (i = 0; i < 7; ++i)
- DUMPREG(HDMI_VSI_DATA(i));
-
-#undef DUMPREG
-}
-
-static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
-{
- if (hdata->is_v13)
- hdmi_v13_regs_dump(hdata, prefix);
- else
- hdmi_v14_regs_dump(hdata, prefix);
-}
-
-static int hdmi_v13_conf_index(struct drm_display_mode *mode)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
- if (hdmi_v13_confs[i].width == mode->hdisplay &&
- hdmi_v13_confs[i].height == mode->vdisplay &&
- hdmi_v13_confs[i].vrefresh == mode->vrefresh &&
- hdmi_v13_confs[i].interlace ==
- ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
- true : false))
- return i;
-
- return -EINVAL;
-}
-
-static int hdmi_v14_conf_index(struct drm_display_mode *mode)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i)
- if (hdmi_confs[i].width == mode->hdisplay &&
- hdmi_confs[i].height == mode->vdisplay &&
- hdmi_confs[i].vrefresh == mode->vrefresh &&
- hdmi_confs[i].interlace ==
- ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
- true : false))
- return i;
-
- return -EINVAL;
-}
-
-static int hdmi_conf_index(struct hdmi_context *hdata,
- struct drm_display_mode *mode)
-{
- if (hdata->is_v13)
- return hdmi_v13_conf_index(mode);
-
- return hdmi_v14_conf_index(mode);
-}
-
-static bool hdmi_is_connected(void *ctx)
-{
- struct hdmi_context *hdata = ctx;
-
- return hdata->hpd;
-}
-
-static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
- u8 *edid, int len)
-{
- struct edid *raw_edid;
- struct hdmi_context *hdata = ctx;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- if (!hdata->ddc_port)
- return -ENODEV;
-
- raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
- if (raw_edid) {
- hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
- memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
- * EDID_LENGTH, len));
- DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
- (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
- raw_edid->width_cm, raw_edid->height_cm);
- } else {
- return -ENODEV;
- }
-
- return 0;
-}
-
-static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
-{
- int i;
-
- DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
- check_timing->xres, check_timing->yres,
- check_timing->refresh, (check_timing->vmode &
- FB_VMODE_INTERLACED) ? true : false);
-
- for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
- if (hdmi_v13_confs[i].width == check_timing->xres &&
- hdmi_v13_confs[i].height == check_timing->yres &&
- hdmi_v13_confs[i].vrefresh == check_timing->refresh &&
- hdmi_v13_confs[i].interlace ==
- ((check_timing->vmode & FB_VMODE_INTERLACED) ?
- true : false))
- return 0;
-
- /* TODO */
-
- return -EINVAL;
-}
-
-static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
-{
- int i;
-
- DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
- check_timing->xres, check_timing->yres,
- check_timing->refresh, (check_timing->vmode &
- FB_VMODE_INTERLACED) ? true : false);
-
- for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++)
- if (hdmi_confs[i].width == check_timing->xres &&
- hdmi_confs[i].height == check_timing->yres &&
- hdmi_confs[i].vrefresh == check_timing->refresh &&
- hdmi_confs[i].interlace ==
- ((check_timing->vmode & FB_VMODE_INTERLACED) ?
- true : false))
- return 0;
-
- /* TODO */
-
- return -EINVAL;
-}
-
-static int hdmi_check_timing(void *ctx, void *timing)
-{
- struct hdmi_context *hdata = ctx;
- struct fb_videomode *check_timing = timing;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres,
- check_timing->yres, check_timing->refresh,
- check_timing->vmode);
-
- if (hdata->is_v13)
- return hdmi_v13_check_timing(check_timing);
- else
- return hdmi_v14_check_timing(check_timing);
-}
-
-static void hdmi_set_acr(u32 freq, u8 *acr)
-{
- u32 n, cts;
-
- switch (freq) {
- case 32000:
- n = 4096;
- cts = 27000;
- break;
- case 44100:
- n = 6272;
- cts = 30000;
- break;
- case 88200:
- n = 12544;
- cts = 30000;
- break;
- case 176400:
- n = 25088;
- cts = 30000;
- break;
- case 48000:
- n = 6144;
- cts = 27000;
- break;
- case 96000:
- n = 12288;
- cts = 27000;
- break;
- case 192000:
- n = 24576;
- cts = 27000;
- break;
- default:
- n = 0;
- cts = 0;
- break;
- }
-
- acr[1] = cts >> 16;
- acr[2] = cts >> 8 & 0xff;
- acr[3] = cts & 0xff;
-
- acr[4] = n >> 16;
- acr[5] = n >> 8 & 0xff;
- acr[6] = n & 0xff;
-}
-
-static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
-{
- hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
- hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
- hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
- hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
- hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
- hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
- hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
- hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
- hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
-
- if (hdata->is_v13)
- hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
- else
- hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
-}
-
-static void hdmi_audio_init(struct hdmi_context *hdata)
-{
- u32 sample_rate, bits_per_sample, frame_size_code;
- u32 data_num, bit_ch, sample_frq;
- u32 val;
- u8 acr[7];
-
- sample_rate = 44100;
- bits_per_sample = 16;
- frame_size_code = 0;
-
- switch (bits_per_sample) {
- case 20:
- data_num = 2;
- bit_ch = 1;
- break;
- case 24:
- data_num = 3;
- bit_ch = 1;
- break;
- default:
- data_num = 1;
- bit_ch = 0;
- break;
- }
-
- hdmi_set_acr(sample_rate, acr);
- hdmi_reg_acr(hdata, acr);
-
- hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
- | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
- | HDMI_I2S_MUX_ENABLE);
-
- hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
- | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
-
- hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
-
- sample_frq = (sample_rate == 44100) ? 0 :
- (sample_rate == 48000) ? 2 :
- (sample_rate == 32000) ? 3 :
- (sample_rate == 96000) ? 0xa : 0x0;
-
- hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
- hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
-
- val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
- hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
-
- /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
- hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
- | HDMI_I2S_SEL_LRCK(6));
- hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
- | HDMI_I2S_SEL_SDATA2(4));
- hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
- | HDMI_I2S_SEL_SDATA2(2));
- hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
-
- /* I2S_CON_1 & 2 */
- hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
- | HDMI_I2S_L_CH_LOW_POL);
- hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
- | HDMI_I2S_SET_BIT_CH(bit_ch)
- | HDMI_I2S_SET_SDATA_BIT(data_num)
- | HDMI_I2S_BASIC_FORMAT);
-
- /* Configure register related to CUV information */
- hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
- | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
- | HDMI_I2S_COPYRIGHT
- | HDMI_I2S_LINEAR_PCM
- | HDMI_I2S_CONSUMER_FORMAT);
- hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
- hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
- hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
- | HDMI_I2S_SET_SMP_FREQ(sample_frq));
- hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
- HDMI_I2S_ORG_SMP_FREQ_44_1
- | HDMI_I2S_WORD_LEN_MAX24_24BITS
- | HDMI_I2S_WORD_LEN_MAX_24BITS);
-
- hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
-}
-
-static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
-{
- if (hdata->dvi_mode)
- return;
-
- hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
- hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
- HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
-}
-
-static void hdmi_conf_reset(struct hdmi_context *hdata)
-{
- u32 reg;
-
- if (hdata->is_v13)
- reg = HDMI_V13_CORE_RSTOUT;
- else
- reg = HDMI_CORE_RSTOUT;
-
- /* resetting HDMI core */
- hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
- mdelay(10);
- hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
- mdelay(10);
-}
-
-static void hdmi_conf_init(struct hdmi_context *hdata)
-{
- /* enable HPD interrupts */
- hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
- HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
- mdelay(10);
- hdmi_reg_writemask(hdata, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
- HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
-
- /* choose HDMI mode */
- hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
- HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
- /* disable bluescreen */
- hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
-
- if (hdata->dvi_mode) {
- /* choose DVI mode */
- hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
- HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
- hdmi_reg_writeb(hdata, HDMI_CON_2,
- HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
- }
-
- if (hdata->is_v13) {
- /* choose bluescreen (fecal) color */
- hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
- hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
- hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
-
- /* enable AVI packet every vsync, fixes purple line problem */
- hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
- /* force RGB, look to CEA-861-D, table 7 for more detail */
- hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
- hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
-
- hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
- hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
- hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
- } else {
- /* enable AVI packet every vsync, fixes purple line problem */
- hdmi_reg_writeb(hdata, HDMI_AVI_CON, 0x02);
- hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5);
- hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
- }
-}
-
-static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
-{
- const struct hdmi_v13_preset_conf *conf =
- hdmi_v13_confs[hdata->cur_conf].conf;
- const struct hdmi_v13_core_regs *core = &conf->core;
- const struct hdmi_v13_tg_regs *tg = &conf->tg;
- int tries;
-
- /* setting core registers */
- hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
- hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
- hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
- hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
- hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
- hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
- hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
- hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
- hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
- hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
- hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
- /* Timing generator registers */
- hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
- hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
- hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
- hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
- hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
- hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
- hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
- hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
-
- /* waiting for HDMIPHY's PLL to get to steady state */
- for (tries = 100; tries; --tries) {
- u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
- if (val & HDMI_PHY_STATUS_READY)
- break;
- mdelay(1);
- }
- /* steady state not achieved */
- if (tries == 0) {
- DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
- hdmi_regs_dump(hdata, "timing apply");
- }
-
- clk_disable(hdata->res.sclk_hdmi);
- clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
- clk_enable(hdata->res.sclk_hdmi);
-
- /* enable HDMI and timing generator */
- hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
- if (core->int_pro_mode[0])
- hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
- HDMI_FIELD_EN);
- else
- hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
-}
-
-static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
-{
- const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf;
- const struct hdmi_core_regs *core = &conf->core;
- const struct hdmi_tg_regs *tg = &conf->tg;
- int tries;
-
- /* setting core registers */
- hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
- hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
- hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
- hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
- hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
- hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
- hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
- hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
- hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
- hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
- hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
- hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
- hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
- hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
- hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
- hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
- hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
- core->v_sync_line_bef_2[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
- core->v_sync_line_bef_2[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
- core->v_sync_line_bef_1[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
- core->v_sync_line_bef_1[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
- core->v_sync_line_aft_2[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
- core->v_sync_line_aft_2[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
- core->v_sync_line_aft_1[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
- core->v_sync_line_aft_1[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
- core->v_sync_line_aft_pxl_2[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
- core->v_sync_line_aft_pxl_2[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
- core->v_sync_line_aft_pxl_1[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
- core->v_sync_line_aft_pxl_1[1]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
- hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
- core->v_sync_line_aft_3[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
- core->v_sync_line_aft_3[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
- core->v_sync_line_aft_4[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
- core->v_sync_line_aft_4[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
- core->v_sync_line_aft_5[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
- core->v_sync_line_aft_5[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
- core->v_sync_line_aft_6[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
- core->v_sync_line_aft_6[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
- core->v_sync_line_aft_pxl_3[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
- core->v_sync_line_aft_pxl_3[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
- core->v_sync_line_aft_pxl_4[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
- core->v_sync_line_aft_pxl_4[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
- core->v_sync_line_aft_pxl_5[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
- core->v_sync_line_aft_pxl_5[1]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
- core->v_sync_line_aft_pxl_6[0]);
- hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
- core->v_sync_line_aft_pxl_6[1]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
- hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
-
- /* Timing generator registers */
- hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
- hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
- hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
- hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
- hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
- hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
- hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
- hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
- hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
- hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
- hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d);
-
- /* waiting for HDMIPHY's PLL to get to steady state */
- for (tries = 100; tries; --tries) {
- u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
- if (val & HDMI_PHY_STATUS_READY)
- break;
- mdelay(1);
- }
- /* steady state not achieved */
- if (tries == 0) {
- DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
- hdmi_regs_dump(hdata, "timing apply");
- }
-
- clk_disable(hdata->res.sclk_hdmi);
- clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
- clk_enable(hdata->res.sclk_hdmi);
-
- /* enable HDMI and timing generator */
- hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
- if (core->int_pro_mode[0])
- hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
- HDMI_FIELD_EN);
- else
- hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
-}
-
-static void hdmi_timing_apply(struct hdmi_context *hdata)
-{
- if (hdata->is_v13)
- hdmi_v13_timing_apply(hdata);
- else
- hdmi_v14_timing_apply(hdata);
-}
-
-static void hdmiphy_conf_reset(struct hdmi_context *hdata)
-{
- u8 buffer[2];
- u32 reg;
-
- clk_disable(hdata->res.sclk_hdmi);
- clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
- clk_enable(hdata->res.sclk_hdmi);
-
- /* operation mode */
- buffer[0] = 0x1f;
- buffer[1] = 0x00;
-
- if (hdata->hdmiphy_port)
- i2c_master_send(hdata->hdmiphy_port, buffer, 2);
-
- if (hdata->is_v13)
- reg = HDMI_V13_PHY_RSTOUT;
- else
- reg = HDMI_PHY_RSTOUT;
-
- /* reset hdmiphy */
- hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
- mdelay(10);
- hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
- mdelay(10);
-}
-
-static void hdmiphy_conf_apply(struct hdmi_context *hdata)
-{
- const u8 *hdmiphy_data;
- u8 buffer[32];
- u8 operation[2];
- u8 read_buffer[32] = {0, };
- int ret;
- int i;
-
- if (!hdata->hdmiphy_port) {
- DRM_ERROR("hdmiphy is not attached\n");
- return;
- }
-
- /* pixel clock */
- if (hdata->is_v13)
- hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
- else
- hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data;
-
- memcpy(buffer, hdmiphy_data, 32);
- ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
- if (ret != 32) {
- DRM_ERROR("failed to configure HDMIPHY via I2C\n");
- return;
- }
-
- mdelay(10);
-
- /* operation mode */
- operation[0] = 0x1f;
- operation[1] = 0x80;
-
- ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
- if (ret != 2) {
- DRM_ERROR("failed to enable hdmiphy\n");
- return;
- }
-
- ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
- if (ret < 0) {
- DRM_ERROR("failed to read hdmiphy config\n");
- return;
- }
-
- for (i = 0; i < ret; i++)
- DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
- "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
-}
-
-static void hdmi_conf_apply(struct hdmi_context *hdata)
-{
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- hdmiphy_conf_reset(hdata);
- hdmiphy_conf_apply(hdata);
-
- mutex_lock(&hdata->hdmi_mutex);
- hdmi_conf_reset(hdata);
- hdmi_conf_init(hdata);
- mutex_unlock(&hdata->hdmi_mutex);
-
- hdmi_audio_init(hdata);
-
- /* setting core registers */
- hdmi_timing_apply(hdata);
- hdmi_audio_control(hdata, true);
-
- hdmi_regs_dump(hdata, "start");
-}
-
-static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_display_mode *m;
- struct hdmi_context *hdata = ctx;
- int index;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- drm_mode_set_crtcinfo(adjusted_mode, 0);
-
- if (hdata->is_v13)
- index = hdmi_v13_conf_index(adjusted_mode);
- else
- index = hdmi_v14_conf_index(adjusted_mode);
-
- /* just return if user desired mode exists. */
- if (index >= 0)
- return;
-
- /*
- * otherwise, find the most suitable mode among modes and change it
- * to adjusted_mode.
- */
- list_for_each_entry(m, &connector->modes, head) {
- if (hdata->is_v13)
- index = hdmi_v13_conf_index(m);
- else
- index = hdmi_v14_conf_index(m);
-
- if (index >= 0) {
- DRM_INFO("desired mode doesn't exist so\n");
- DRM_INFO("use the most suitable mode among modes.\n");
- memcpy(adjusted_mode, m, sizeof(*m));
- break;
- }
- }
-}
-
-static void hdmi_mode_set(void *ctx, void *mode)
-{
- struct hdmi_context *hdata = ctx;
- int conf_idx;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- conf_idx = hdmi_conf_index(hdata, mode);
- if (conf_idx >= 0)
- hdata->cur_conf = conf_idx;
- else
- DRM_DEBUG_KMS("not supported mode\n");
-}
-
-static void hdmi_get_max_resol(void *ctx, unsigned int *width,
- unsigned int *height)
-{
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- *width = MAX_WIDTH;
- *height = MAX_HEIGHT;
-}
-
-static void hdmi_commit(void *ctx)
-{
- struct hdmi_context *hdata = ctx;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- hdmi_conf_apply(hdata);
-}
-
-static void hdmi_poweron(struct hdmi_context *hdata)
-{
- struct hdmi_resources *res = &hdata->res;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- mutex_lock(&hdata->hdmi_mutex);
- if (hdata->powered) {
- mutex_unlock(&hdata->hdmi_mutex);
- return;
- }
-
- hdata->powered = true;
-
- if (hdata->cfg_hpd)
- hdata->cfg_hpd(true);
- mutex_unlock(&hdata->hdmi_mutex);
-
- pm_runtime_get_sync(hdata->dev);
-
- regulator_bulk_enable(res->regul_count, res->regul_bulk);
- clk_enable(res->hdmiphy);
- clk_enable(res->hdmi);
- clk_enable(res->sclk_hdmi);
-}
-
-static void hdmi_poweroff(struct hdmi_context *hdata)
-{
- struct hdmi_resources *res = &hdata->res;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- mutex_lock(&hdata->hdmi_mutex);
- if (!hdata->powered)
- goto out;
- mutex_unlock(&hdata->hdmi_mutex);
-
- /*
- * The TV power domain needs any condition of hdmiphy to turn off and
- * its reset state seems to meet the condition.
- */
- hdmiphy_conf_reset(hdata);
-
- clk_disable(res->sclk_hdmi);
- clk_disable(res->hdmi);
- clk_disable(res->hdmiphy);
- regulator_bulk_disable(res->regul_count, res->regul_bulk);
-
- pm_runtime_put_sync(hdata->dev);
-
- mutex_lock(&hdata->hdmi_mutex);
- if (hdata->cfg_hpd)
- hdata->cfg_hpd(false);
-
- hdata->powered = false;
-
-out:
- mutex_unlock(&hdata->hdmi_mutex);
-}
-
-static void hdmi_dpms(void *ctx, int mode)
-{
- struct hdmi_context *hdata = ctx;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- hdmi_poweron(hdata);
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- hdmi_poweroff(hdata);
- break;
- default:
- DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
- break;
- }
-}
-
-static struct exynos_hdmi_ops hdmi_ops = {
- /* display */
- .is_connected = hdmi_is_connected,
- .get_edid = hdmi_get_edid,
- .check_timing = hdmi_check_timing,
-
- /* manager */
- .mode_fixup = hdmi_mode_fixup,
- .mode_set = hdmi_mode_set,
- .get_max_resol = hdmi_get_max_resol,
- .commit = hdmi_commit,
- .dpms = hdmi_dpms,
-};
-
-static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
-{
- struct exynos_drm_hdmi_context *ctx = arg;
- struct hdmi_context *hdata = ctx->ctx;
-
- if (!hdata->get_hpd)
- goto out;
-
- mutex_lock(&hdata->hdmi_mutex);
- hdata->hpd = hdata->get_hpd();
- mutex_unlock(&hdata->hdmi_mutex);
-
- if (ctx->drm_dev)
- drm_helper_hpd_irq_event(ctx->drm_dev);
-
-out:
- return IRQ_HANDLED;
-}
-
-static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
-{
- struct exynos_drm_hdmi_context *ctx = arg;
- struct hdmi_context *hdata = ctx->ctx;
- u32 intc_flag;
-
- intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
- /* clearing flags for HPD plug/unplug */
- if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
- DRM_DEBUG_KMS("unplugged\n");
- hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
- HDMI_INTC_FLAG_HPD_UNPLUG);
- }
- if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
- DRM_DEBUG_KMS("plugged\n");
- hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
- HDMI_INTC_FLAG_HPD_PLUG);
- }
-
- mutex_lock(&hdata->hdmi_mutex);
- hdata->hpd = hdmi_reg_read(hdata, HDMI_HPD_STATUS);
- if (hdata->powered && hdata->hpd) {
- mutex_unlock(&hdata->hdmi_mutex);
- goto out;
- }
- mutex_unlock(&hdata->hdmi_mutex);
-
- if (ctx->drm_dev)
- drm_helper_hpd_irq_event(ctx->drm_dev);
-
-out:
- return IRQ_HANDLED;
-}
-
-static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
-{
- struct device *dev = hdata->dev;
- struct hdmi_resources *res = &hdata->res;
- static char *supply[] = {
- /* FIXME: control HDMI_EN gpio using fixed regulator */
- /* "hdmi-en", */
- "vdd",
- "vdd_osc",
- "vdd_pll",
- };
- int i, ret;
-
- DRM_DEBUG_KMS("HDMI resource init\n");
-
- memset(res, 0, sizeof *res);
-
- /* get clocks, power */
- res->hdmi = clk_get(dev, "hdmi");
- if (IS_ERR_OR_NULL(res->hdmi)) {
- DRM_ERROR("failed to get clock 'hdmi'\n");
- goto fail;
- }
- res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
- if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
- DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
- goto fail;
- }
- res->sclk_pixel = clk_get(dev, "sclk_pixel");
- if (IS_ERR_OR_NULL(res->sclk_pixel)) {
- DRM_ERROR("failed to get clock 'sclk_pixel'\n");
- goto fail;
- }
- res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
- if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
- DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
- goto fail;
- }
- res->hdmiphy = clk_get(dev, "hdmiphy");
- if (IS_ERR_OR_NULL(res->hdmiphy)) {
- DRM_ERROR("failed to get clock 'hdmiphy'\n");
- goto fail;
- }
-
- clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
-
- res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
- sizeof res->regul_bulk[0], GFP_KERNEL);
- if (!res->regul_bulk) {
- DRM_ERROR("failed to get memory for regulators\n");
- goto fail;
- }
- for (i = 0; i < ARRAY_SIZE(supply); ++i) {
- res->regul_bulk[i].supply = supply[i];
- res->regul_bulk[i].consumer = NULL;
- }
- ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
- if (ret) {
- DRM_ERROR("failed to get regulators\n");
- goto fail;
- }
- res->regul_count = ARRAY_SIZE(supply);
-
- return 0;
-fail:
- DRM_ERROR("HDMI resource init - failed\n");
- return -ENODEV;
-}
-
-static int hdmi_resources_cleanup(struct hdmi_context *hdata)
-{
- struct hdmi_resources *res = &hdata->res;
-
- regulator_bulk_free(res->regul_count, res->regul_bulk);
- /* kfree is NULL-safe */
- kfree(res->regul_bulk);
- if (!IS_ERR_OR_NULL(res->hdmiphy))
- clk_put(res->hdmiphy);
- if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
- clk_put(res->sclk_hdmiphy);
- if (!IS_ERR_OR_NULL(res->sclk_pixel))
- clk_put(res->sclk_pixel);
- if (!IS_ERR_OR_NULL(res->sclk_hdmi))
- clk_put(res->sclk_hdmi);
- if (!IS_ERR_OR_NULL(res->hdmi))
- clk_put(res->hdmi);
- memset(res, 0, sizeof *res);
-
- return 0;
-}
-
-static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
-
-void hdmi_attach_ddc_client(struct i2c_client *ddc)
-{
- if (ddc)
- hdmi_ddc = ddc;
-}
-
-void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
-{
- if (hdmiphy)
- hdmi_hdmiphy = hdmiphy;
-}
-
-static int __devinit hdmi_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct exynos_drm_hdmi_context *drm_hdmi_ctx;
- struct hdmi_context *hdata;
- struct exynos_drm_hdmi_pdata *pdata;
- struct resource *res;
- int ret;
-
- DRM_DEBUG_KMS("[%d]\n", __LINE__);
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- DRM_ERROR("no platform data specified\n");
- return -EINVAL;
- }
-
- drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
- if (!drm_hdmi_ctx) {
- DRM_ERROR("failed to allocate common hdmi context.\n");
- return -ENOMEM;
- }
-
- hdata = kzalloc(sizeof(struct hdmi_context), GFP_KERNEL);
- if (!hdata) {
- DRM_ERROR("out of memory\n");
- kfree(drm_hdmi_ctx);
- return -ENOMEM;
- }
-
- mutex_init(&hdata->hdmi_mutex);
-
- drm_hdmi_ctx->ctx = (void *)hdata;
- hdata->parent_ctx = (void *)drm_hdmi_ctx;
-
- platform_set_drvdata(pdev, drm_hdmi_ctx);
-
- hdata->is_v13 = pdata->is_v13;
- hdata->cfg_hpd = pdata->cfg_hpd;
- hdata->get_hpd = pdata->get_hpd;
- hdata->dev = dev;
-
- ret = hdmi_resources_init(hdata);
- if (ret) {
- ret = -EINVAL;
- goto err_data;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- DRM_ERROR("failed to find registers\n");
- ret = -ENOENT;
- goto err_resource;
- }
-
- hdata->regs_res = request_mem_region(res->start, resource_size(res),
- dev_name(dev));
- if (!hdata->regs_res) {
- DRM_ERROR("failed to claim register region\n");
- ret = -ENOENT;
- goto err_resource;
- }
-
- hdata->regs = ioremap(res->start, resource_size(res));
- if (!hdata->regs) {
- DRM_ERROR("failed to map registers\n");
- ret = -ENXIO;
- goto err_req_region;
- }
-
- /* DDC i2c driver */
- if (i2c_add_driver(&ddc_driver)) {
- DRM_ERROR("failed to register ddc i2c driver\n");
- ret = -ENOENT;
- goto err_iomap;
- }
-
- hdata->ddc_port = hdmi_ddc;
-
- /* hdmiphy i2c driver */
- if (i2c_add_driver(&hdmiphy_driver)) {
- DRM_ERROR("failed to register hdmiphy i2c driver\n");
- ret = -ENOENT;
- goto err_ddc;
- }
-
- hdata->hdmiphy_port = hdmi_hdmiphy;
-
- hdata->external_irq = platform_get_irq_byname(pdev, "external_irq");
- if (hdata->external_irq < 0) {
- DRM_ERROR("failed to get platform irq\n");
- ret = hdata->external_irq;
- goto err_hdmiphy;
- }
-
- hdata->internal_irq = platform_get_irq_byname(pdev, "internal_irq");
- if (hdata->internal_irq < 0) {
- DRM_ERROR("failed to get platform internal irq\n");
- ret = hdata->internal_irq;
- goto err_hdmiphy;
- }
-
- ret = request_threaded_irq(hdata->external_irq, NULL,
- hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "hdmi_external", drm_hdmi_ctx);
- if (ret) {
- DRM_ERROR("failed to register hdmi internal interrupt\n");
- goto err_hdmiphy;
- }
-
- if (hdata->cfg_hpd)
- hdata->cfg_hpd(false);
-
- ret = request_threaded_irq(hdata->internal_irq, NULL,
- hdmi_internal_irq_thread, IRQF_ONESHOT,
- "hdmi_internal", drm_hdmi_ctx);
- if (ret) {
- DRM_ERROR("failed to register hdmi internal interrupt\n");
- goto err_free_irq;
- }
-
- /* register specific callbacks to common hdmi. */
- exynos_hdmi_ops_register(&hdmi_ops);
-
- pm_runtime_enable(dev);
-
- return 0;
-
-err_free_irq:
- free_irq(hdata->external_irq, drm_hdmi_ctx);
-err_hdmiphy:
- i2c_del_driver(&hdmiphy_driver);
-err_ddc:
- i2c_del_driver(&ddc_driver);
-err_iomap:
- iounmap(hdata->regs);
-err_req_region:
- release_mem_region(hdata->regs_res->start,
- resource_size(hdata->regs_res));
-err_resource:
- hdmi_resources_cleanup(hdata);
-err_data:
- kfree(hdata);
- kfree(drm_hdmi_ctx);
- return ret;
-}
-
-static int __devexit hdmi_remove(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
- struct hdmi_context *hdata = ctx->ctx;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- pm_runtime_disable(dev);
-
- free_irq(hdata->internal_irq, hdata);
-
- hdmi_resources_cleanup(hdata);
-
- iounmap(hdata->regs);
-
- release_mem_region(hdata->regs_res->start,
- resource_size(hdata->regs_res));
-
- /* hdmiphy i2c driver */
- i2c_del_driver(&hdmiphy_driver);
- /* DDC i2c driver */
- i2c_del_driver(&ddc_driver);
-
- kfree(hdata);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int hdmi_suspend(struct device *dev)
-{
- struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
- struct hdmi_context *hdata = ctx->ctx;
-
- disable_irq(hdata->internal_irq);
- disable_irq(hdata->external_irq);
-
- hdata->hpd = false;
- if (ctx->drm_dev)
- drm_helper_hpd_irq_event(ctx->drm_dev);
-
- hdmi_poweroff(hdata);
-
- return 0;
-}
-
-static int hdmi_resume(struct device *dev)
-{
- struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
- struct hdmi_context *hdata = ctx->ctx;
-
- enable_irq(hdata->external_irq);
- enable_irq(hdata->internal_irq);
- return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(hdmi_pm_ops, hdmi_suspend, hdmi_resume);
-
-struct platform_driver hdmi_driver = {
- .probe = hdmi_probe,
- .remove = __devexit_p(hdmi_remove),
- .driver = {
- .name = "exynos4-hdmi",
- .owner = THIS_MODULE,
- .pm = &hdmi_pm_ops,
- },
-};
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_hdmi.h b/drivers/gpu/drm/exynos_tmp/exynos_hdmi.h
deleted file mode 100644
index 1c3b6d8..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_hdmi.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- * Inki Dae <inki.dae@samsung.com>
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_HDMI_H_
-#define _EXYNOS_HDMI_H_
-
-void hdmi_attach_ddc_client(struct i2c_client *ddc);
-void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy);
-
-extern struct i2c_driver hdmiphy_driver;
-extern struct i2c_driver ddc_driver;
-
-#endif
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_hdmiphy.c b/drivers/gpu/drm/exynos_tmp/exynos_hdmiphy.c
deleted file mode 100644
index 9fe2995..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_hdmiphy.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- * Inki Dae <inki.dae@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include "drmP.h"
-
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_hdmi.h"
-
-
-static int hdmiphy_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- hdmi_attach_hdmiphy_client(client);
-
- dev_info(&client->adapter->dev, "attached s5p_hdmiphy "
- "into i2c adapter successfully\n");
-
- return 0;
-}
-
-static int hdmiphy_remove(struct i2c_client *client)
-{
- dev_info(&client->adapter->dev, "detached s5p_hdmiphy "
- "from i2c adapter successfully\n");
-
- return 0;
-}
-
-static const struct i2c_device_id hdmiphy_id[] = {
- { "s5p_hdmiphy", 0 },
- { },
-};
-
-struct i2c_driver hdmiphy_driver = {
- .driver = {
- .name = "s5p-hdmiphy",
- .owner = THIS_MODULE,
- },
- .id_table = hdmiphy_id,
- .probe = hdmiphy_probe,
- .remove = __devexit_p(hdmiphy_remove),
- .command = NULL,
-};
-EXPORT_SYMBOL(hdmiphy_driver);
diff --git a/drivers/gpu/drm/exynos_tmp/exynos_mixer.c b/drivers/gpu/drm/exynos_tmp/exynos_mixer.c
deleted file mode 100644
index 68ef010..0000000
--- a/drivers/gpu/drm/exynos_tmp/exynos_mixer.c
+++ /dev/null
@@ -1,1109 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- * Seung-Woo Kim <sw0312.kim@samsung.com>
- * Inki Dae <inki.dae@samsung.com>
- * Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * Based on drivers/media/video/s5p-tv/mixer_reg.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include "drmP.h"
-
-#include "regs-mixer.h"
-#include "regs-vp.h"
-
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/pm_runtime.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
-
-#include <drm/exynos_drm.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_hdmi.h"
-
-#define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
-
-struct hdmi_win_data {
- dma_addr_t dma_addr;
- void __iomem *vaddr;
- dma_addr_t chroma_dma_addr;
- void __iomem *chroma_vaddr;
- uint32_t pixel_format;
- unsigned int bpp;
- unsigned int crtc_x;
- unsigned int crtc_y;
- unsigned int crtc_width;
- unsigned int crtc_height;
- unsigned int fb_x;
- unsigned int fb_y;
- unsigned int fb_width;
- unsigned int fb_height;
- unsigned int src_width;
- unsigned int src_height;
- unsigned int mode_width;
- unsigned int mode_height;
- unsigned int scan_flags;
-};
-
-struct mixer_resources {
- int irq;
- void __iomem *mixer_regs;
- void __iomem *vp_regs;
- spinlock_t reg_slock;
- struct clk *mixer;
- struct clk *vp;
- struct clk *sclk_mixer;
- struct clk *sclk_hdmi;
- struct clk *sclk_dac;
-};
-
-struct mixer_context {
- struct device *dev;
- int pipe;
- bool interlace;
- bool powered;
- u32 int_en;
-
- struct mutex mixer_mutex;
- struct mixer_resources mixer_res;
- struct hdmi_win_data win_data[MIXER_WIN_NR];
-};
-
-static const u8 filter_y_horiz_tap8[] = {
- 0, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 0, 0, 0,
- 0, 2, 4, 5, 6, 6, 6, 6,
- 6, 5, 5, 4, 3, 2, 1, 1,
- 0, -6, -12, -16, -18, -20, -21, -20,
- -20, -18, -16, -13, -10, -8, -5, -2,
- 127, 126, 125, 121, 114, 107, 99, 89,
- 79, 68, 57, 46, 35, 25, 16, 8,
-};
-
-static const u8 filter_y_vert_tap4[] = {
- 0, -3, -6, -8, -8, -8, -8, -7,
- -6, -5, -4, -3, -2, -1, -1, 0,
- 127, 126, 124, 118, 111, 102, 92, 81,
- 70, 59, 48, 37, 27, 19, 11, 5,
- 0, 5, 11, 19, 27, 37, 48, 59,
- 70, 81, 92, 102, 111, 118, 124, 126,
- 0, 0, -1, -1, -2, -3, -4, -5,
- -6, -7, -8, -8, -8, -8, -6, -3,
-};
-
-static const u8 filter_cr_horiz_tap4[] = {
- 0, -3, -6, -8, -8, -8, -8, -7,
- -6, -5, -4, -3, -2, -1, -1, 0,
- 127, 126, 124, 118, 111, 102, 92, 81,
- 70, 59, 48, 37, 27, 19, 11, 5,
-};
-
-static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
-{
- return readl(res->vp_regs + reg_id);
-}
-
-static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
- u32 val)
-{
- writel(val, res->vp_regs + reg_id);
-}
-
-static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
- u32 val, u32 mask)
-{
- u32 old = vp_reg_read(res, reg_id);
-
- val = (val & mask) | (old & ~mask);
- writel(val, res->vp_regs + reg_id);
-}
-
-static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
-{
- return readl(res->mixer_regs + reg_id);
-}
-
-static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
- u32 val)
-{
- writel(val, res->mixer_regs + reg_id);
-}
-
-static inline void mixer_reg_writemask(struct mixer_resources *res,
- u32 reg_id, u32 val, u32 mask)
-{
- u32 old = mixer_reg_read(res, reg_id);
-
- val = (val & mask) | (old & ~mask);
- writel(val, res->mixer_regs + reg_id);
-}
-
-static void mixer_regs_dump(struct mixer_context *ctx)
-{
-#define DUMPREG(reg_id) \
-do { \
- DRM_DEBUG_KMS(#reg_id " = %08x\n", \
- (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
-} while (0)
-
- DUMPREG(MXR_STATUS);
- DUMPREG(MXR_CFG);
- DUMPREG(MXR_INT_EN);
- DUMPREG(MXR_INT_STATUS);
-
- DUMPREG(MXR_LAYER_CFG);
- DUMPREG(MXR_VIDEO_CFG);
-
- DUMPREG(MXR_GRAPHIC0_CFG);
- DUMPREG(MXR_GRAPHIC0_BASE);
- DUMPREG(MXR_GRAPHIC0_SPAN);
- DUMPREG(MXR_GRAPHIC0_WH);
- DUMPREG(MXR_GRAPHIC0_SXY);
- DUMPREG(MXR_GRAPHIC0_DXY);
-
- DUMPREG(MXR_GRAPHIC1_CFG);
- DUMPREG(MXR_GRAPHIC1_BASE);
- DUMPREG(MXR_GRAPHIC1_SPAN);
- DUMPREG(MXR_GRAPHIC1_WH);
- DUMPREG(MXR_GRAPHIC1_SXY);
- DUMPREG(MXR_GRAPHIC1_DXY);
-#undef DUMPREG
-}
-
-static void vp_regs_dump(struct mixer_context *ctx)
-{
-#define DUMPREG(reg_id) \
-do { \
- DRM_DEBUG_KMS(#reg_id " = %08x\n", \
- (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
-} while (0)
-
- DUMPREG(VP_ENABLE);
- DUMPREG(VP_SRESET);
- DUMPREG(VP_SHADOW_UPDATE);
- DUMPREG(VP_FIELD_ID);
- DUMPREG(VP_MODE);
- DUMPREG(VP_IMG_SIZE_Y);
- DUMPREG(VP_IMG_SIZE_C);
- DUMPREG(VP_PER_RATE_CTRL);
- DUMPREG(VP_TOP_Y_PTR);
- DUMPREG(VP_BOT_Y_PTR);
- DUMPREG(VP_TOP_C_PTR);
- DUMPREG(VP_BOT_C_PTR);
- DUMPREG(VP_ENDIAN_MODE);
- DUMPREG(VP_SRC_H_POSITION);
- DUMPREG(VP_SRC_V_POSITION);
- DUMPREG(VP_SRC_WIDTH);
- DUMPREG(VP_SRC_HEIGHT);
- DUMPREG(VP_DST_H_POSITION);
- DUMPREG(VP_DST_V_POSITION);
- DUMPREG(VP_DST_WIDTH);
- DUMPREG(VP_DST_HEIGHT);
- DUMPREG(VP_H_RATIO);
- DUMPREG(VP_V_RATIO);
-
-#undef DUMPREG
-}
-
-static inline void vp_filter_set(struct mixer_resources *res,
- int reg_id, const u8 *data, unsigned int size)
-{
- /* assure 4-byte align */
- BUG_ON(size & 3);
- for (; size; size -= 4, reg_id += 4, data += 4) {
- u32 val = (data[0] << 24) | (data[1] << 16) |
- (data[2] << 8) | data[3];
- vp_reg_write(res, reg_id, val);
- }
-}
-
-static void vp_default_filter(struct mixer_resources *res)
-{
- vp_filter_set(res, VP_POLY8_Y0_LL,
- filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
- vp_filter_set(res, VP_POLY4_Y0_LL,
- filter_y_vert_tap4, sizeof filter_y_vert_tap4);
- vp_filter_set(res, VP_POLY4_C0_LL,
- filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
-}
-
-static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
-{
- struct mixer_resources *res = &ctx->mixer_res;
-
- /* block update on vsync */
- mixer_reg_writemask(res, MXR_STATUS, enable ?
- MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
-
- vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
- VP_SHADOW_UPDATE_ENABLE : 0);
-}
-
-static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
-{
- struct mixer_resources *res = &ctx->mixer_res;
- u32 val;
-
- /* choosing between interlace and progressive mode */
- val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
- MXR_CFG_SCAN_PROGRASSIVE);
-
- /* choosing between porper HD and SD mode */
- if (height == 480)
- val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
- else if (height == 576)
- val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
- else if (height == 720)
- val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
- else if (height == 1080)
- val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
- else
- val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
-
- mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
-}
-
-static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
-{
- struct mixer_resources *res = &ctx->mixer_res;
- u32 val;
-
- if (height == 480) {
- val = MXR_CFG_RGB601_0_255;
- } else if (height == 576) {
- val = MXR_CFG_RGB601_0_255;
- } else if (height == 720) {
- val = MXR_CFG_RGB709_16_235;
- mixer_reg_write(res, MXR_CM_COEFF_Y,
- (1 << 30) | (94 << 20) | (314 << 10) |
- (32 << 0));
- mixer_reg_write(res, MXR_CM_COEFF_CB,
- (972 << 20) | (851 << 10) | (225 << 0));
- mixer_reg_write(res, MXR_CM_COEFF_CR,
- (225 << 20) | (820 << 10) | (1004 << 0));
- } else if (height == 1080) {
- val = MXR_CFG_RGB709_16_235;
- mixer_reg_write(res, MXR_CM_COEFF_Y,
- (1 << 30) | (94 << 20) | (314 << 10) |
- (32 << 0));
- mixer_reg_write(res, MXR_CM_COEFF_CB,
- (972 << 20) | (851 << 10) | (225 << 0));
- mixer_reg_write(res, MXR_CM_COEFF_CR,
- (225 << 20) | (820 << 10) | (1004 << 0));
- } else {
- val = MXR_CFG_RGB709_16_235;
- mixer_reg_write(res, MXR_CM_COEFF_Y,
- (1 << 30) | (94 << 20) | (314 << 10) |
- (32 << 0));
- mixer_reg_write(res, MXR_CM_COEFF_CB,
- (972 << 20) | (851 << 10) | (225 << 0));
- mixer_reg_write(res, MXR_CM_COEFF_CR,
- (225 << 20) | (820 << 10) | (1004 << 0));
- }
-
- mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
-}
-
-static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
-{
- struct mixer_resources *res = &ctx->mixer_res;
- u32 val = enable ? ~0 : 0;
-
- switch (win) {
- case 0:
- mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
- break;
- case 1:
- mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
- break;
- case 2:
- vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
- mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE);
- break;
- }
-}
-
-static void mixer_run(struct mixer_context *ctx)
-{
- struct mixer_resources *res = &ctx->mixer_res;
-
- mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
-
- mixer_regs_dump(ctx);
-}
-
-static void vp_video_buffer(struct mixer_context *ctx, int win)
-{
- struct mixer_resources *res = &ctx->mixer_res;
- unsigned long flags;
- struct hdmi_win_data *win_data;
- unsigned int x_ratio, y_ratio;
- unsigned int buf_num;
- dma_addr_t luma_addr[2], chroma_addr[2];
- bool tiled_mode = false;
- bool crcb_mode = false;
- u32 val;
-
- win_data = &ctx->win_data[win];
-
- switch (win_data->pixel_format) {
- case DRM_FORMAT_NV12MT:
- tiled_mode = true;
- case DRM_FORMAT_NV12M:
- crcb_mode = false;
- buf_num = 2;
- break;
- /* TODO: single buffer format NV12, NV21 */
- default:
- /* ignore pixel format at disable time */
- if (!win_data->dma_addr)
- break;
-
- DRM_ERROR("pixel format for vp is wrong [%d].\n",
- win_data->pixel_format);
- return;
- }
-
- /* scaling feature: (src << 16) / dst */
- x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
- y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
-
- if (buf_num == 2) {
- luma_addr[0] = win_data->dma_addr;
- chroma_addr[0] = win_data->chroma_dma_addr;
- } else {
- luma_addr[0] = win_data->dma_addr;
- chroma_addr[0] = win_data->dma_addr
- + (win_data->fb_width * win_data->fb_height);
- }
-
- if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
- ctx->interlace = true;
- if (tiled_mode) {
- luma_addr[1] = luma_addr[0] + 0x40;
- chroma_addr[1] = chroma_addr[0] + 0x40;
- } else {
- luma_addr[1] = luma_addr[0] + win_data->fb_width;
- chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
- }
- } else {
- ctx->interlace = false;
- luma_addr[1] = 0;
- chroma_addr[1] = 0;
- }
-
- spin_lock_irqsave(&res->reg_slock, flags);
- mixer_vsync_set_update(ctx, false);
-
- /* interlace or progressive scan mode */
- val = (ctx->interlace ? ~0 : 0);
- vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
-
- /* setup format */
- val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
- val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
- vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
-
- /* setting size of input image */
- vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
- VP_IMG_VSIZE(win_data->fb_height));
- /* chroma height has to reduced by 2 to avoid chroma distorions */
- vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
- VP_IMG_VSIZE(win_data->fb_height / 2));
-
- vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
- vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
- vp_reg_write(res, VP_SRC_H_POSITION,
- VP_SRC_H_POSITION_VAL(win_data->fb_x));
- vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
-
- vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
- vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
- if (ctx->interlace) {
- vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
- vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
- } else {
- vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
- vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
- }
-
- vp_reg_write(res, VP_H_RATIO, x_ratio);
- vp_reg_write(res, VP_V_RATIO, y_ratio);
-
- vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
-
- /* set buffer address to vp */
- vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
- vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
- vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
- vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
-
- mixer_cfg_scan(ctx, win_data->mode_height);
- mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
- mixer_cfg_layer(ctx, win, true);
- mixer_run(ctx);
-
- mixer_vsync_set_update(ctx, true);
- spin_unlock_irqrestore(&res->reg_slock, flags);
-
- vp_regs_dump(ctx);
-}
-
-static void mixer_graph_buffer(struct mixer_context *ctx, int win)
-{
- struct mixer_resources *res = &ctx->mixer_res;
- unsigned long flags;
- struct hdmi_win_data *win_data;
- unsigned int x_ratio, y_ratio;
- unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
- dma_addr_t dma_addr;
- unsigned int fmt;
- u32 val;
-
- win_data = &ctx->win_data[win];
-
- #define RGB565 4
- #define ARGB1555 5
- #define ARGB4444 6
- #define ARGB8888 7
-
- switch (win_data->bpp) {
- case 16:
- fmt = ARGB4444;
- break;
- case 32:
- fmt = ARGB8888;
- break;
- default:
- fmt = ARGB8888;
- }
-
- /* 2x scaling feature */
- x_ratio = 0;
- y_ratio = 0;
-
- dst_x_offset = win_data->crtc_x;
- dst_y_offset = win_data->crtc_y;
-
- /* converting dma address base and source offset */
- dma_addr = win_data->dma_addr
- + (win_data->fb_x * win_data->bpp >> 3)
- + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
- src_x_offset = 0;
- src_y_offset = 0;
-
- if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
- ctx->interlace = true;
- else
- ctx->interlace = false;
-
- spin_lock_irqsave(&res->reg_slock, flags);
- mixer_vsync_set_update(ctx, false);
-
- /* setup format */
- mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
- MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
-
- /* setup geometry */
- mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
-
- val = MXR_GRP_WH_WIDTH(win_data->crtc_width);
- val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
- val |= MXR_GRP_WH_H_SCALE(x_ratio);
- val |= MXR_GRP_WH_V_SCALE(y_ratio);
- mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
-
- /* setup offsets in source image */
- val = MXR_GRP_SXY_SX(src_x_offset);
- val |= MXR_GRP_SXY_SY(src_y_offset);
- mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
-
- /* setup offsets in display image */
- val = MXR_GRP_DXY_DX(dst_x_offset);
- val |= MXR_GRP_DXY_DY(dst_y_offset);
- mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
-
- /* set buffer address to mixer */
- mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
-
- mixer_cfg_scan(ctx, win_data->mode_height);
- mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
- mixer_cfg_layer(ctx, win, true);
- mixer_run(ctx);
-
- mixer_vsync_set_update(ctx, true);
- spin_unlock_irqrestore(&res->reg_slock, flags);
-}
-
-static void vp_win_reset(struct mixer_context *ctx)
-{
- struct mixer_resources *res = &ctx->mixer_res;
- int tries = 100;
-
- vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
- for (tries = 100; tries; --tries) {
- /* waiting until VP_SRESET_PROCESSING is 0 */
- if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
- break;
- mdelay(10);
- }
- WARN(tries == 0, "failed to reset Video Processor\n");
-}
-
-static void mixer_win_reset(struct mixer_context *ctx)
-{
- struct mixer_resources *res = &ctx->mixer_res;
- unsigned long flags;
- u32 val; /* value stored to register */
-
- spin_lock_irqsave(&res->reg_slock, flags);
- mixer_vsync_set_update(ctx, false);
-
- mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
-
- /* set output in RGB888 mode */
- mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
-
- /* 16 beat burst in DMA */
- mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
- MXR_STATUS_BURST_MASK);
-
- /* setting default layer priority: layer1 > layer0 > video
- * because typical usage scenario would be
- * layer1 - OSD
- * layer0 - framebuffer
- * video - video overlay
- */
- val = MXR_LAYER_CFG_GRP1_VAL(3);
- val |= MXR_LAYER_CFG_GRP0_VAL(2);
- val |= MXR_LAYER_CFG_VP_VAL(1);
- mixer_reg_write(res, MXR_LAYER_CFG, val);
-
- /* setting background color */
- mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
- mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
- mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
-
- /* setting graphical layers */
-
- val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
- val |= MXR_GRP_CFG_WIN_BLEND_EN;
- val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
-
- /* the same configuration for both layers */
- mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
-
- val |= MXR_GRP_CFG_BLEND_PRE_MUL;
- val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
- mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
-
- /* configuration of Video Processor Registers */
- vp_win_reset(ctx);
- vp_default_filter(res);
-
- /* disable all layers */
- mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
- mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
- mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
-
- mixer_vsync_set_update(ctx, true);
- spin_unlock_irqrestore(&res->reg_slock, flags);
-}
-
-static void mixer_poweron(struct mixer_context *ctx)
-{
- struct mixer_resources *res = &ctx->mixer_res;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- mutex_lock(&ctx->mixer_mutex);
- if (ctx->powered) {
- mutex_unlock(&ctx->mixer_mutex);
- return;
- }
- ctx->powered = true;
- mutex_unlock(&ctx->mixer_mutex);
-
- pm_runtime_get_sync(ctx->dev);
-
- clk_enable(res->mixer);
- clk_enable(res->vp);
- clk_enable(res->sclk_mixer);
-
- mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
- mixer_win_reset(ctx);
-}
-
-static void mixer_poweroff(struct mixer_context *ctx)
-{
- struct mixer_resources *res = &ctx->mixer_res;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- mutex_lock(&ctx->mixer_mutex);
- if (!ctx->powered)
- goto out;
- mutex_unlock(&ctx->mixer_mutex);
-
- ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
-
- clk_disable(res->mixer);
- clk_disable(res->vp);
- clk_disable(res->sclk_mixer);
-
- pm_runtime_put_sync(ctx->dev);
-
- mutex_lock(&ctx->mixer_mutex);
- ctx->powered = false;
-
-out:
- mutex_unlock(&ctx->mixer_mutex);
-}
-
-static int mixer_enable_vblank(void *ctx, int pipe)
-{
- struct mixer_context *mixer_ctx = ctx;
- struct mixer_resources *res = &mixer_ctx->mixer_res;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- mixer_ctx->pipe = pipe;
-
- /* enable vsync interrupt */
- mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
- MXR_INT_EN_VSYNC);
-
- return 0;
-}
-
-static void mixer_disable_vblank(void *ctx)
-{
- struct mixer_context *mixer_ctx = ctx;
- struct mixer_resources *res = &mixer_ctx->mixer_res;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- /* disable vsync interrupt */
- mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
-}
-
-static void mixer_dpms(void *ctx, int mode)
-{
- struct mixer_context *mixer_ctx = ctx;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- mixer_poweron(mixer_ctx);
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- mixer_poweroff(mixer_ctx);
- break;
- default:
- DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
- break;
- }
-}
-
-static void mixer_win_mode_set(void *ctx,
- struct exynos_drm_overlay *overlay)
-{
- struct mixer_context *mixer_ctx = ctx;
- struct hdmi_win_data *win_data;
- int win;
-
- DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
- if (!overlay) {
- DRM_ERROR("overlay is NULL\n");
- return;
- }
-
- DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
- overlay->fb_width, overlay->fb_height,
- overlay->fb_x, overlay->fb_y,
- overlay->crtc_width, overlay->crtc_height,
- overlay->crtc_x, overlay->crtc_y);
-
- win = overlay->zpos;
- if (win == DEFAULT_ZPOS)
- win = MIXER_DEFAULT_WIN;
-
- if (win < 0 || win > MIXER_WIN_NR) {
- DRM_ERROR("mixer window[%d] is wrong\n", win);
- return;
- }
-
- win_data = &mixer_ctx->win_data[win];
-
- win_data->dma_addr = overlay->dma_addr[0];
- win_data->vaddr = overlay->vaddr[0];
- win_data->chroma_dma_addr = overlay->dma_addr[1];
- win_data->chroma_vaddr = overlay->vaddr[1];
- win_data->pixel_format = overlay->pixel_format;
- win_data->bpp = overlay->bpp;
-
- win_data->crtc_x = overlay->crtc_x;
- win_data->crtc_y = overlay->crtc_y;
- win_data->crtc_width = overlay->crtc_width;
- win_data->crtc_height = overlay->crtc_height;
-
- win_data->fb_x = overlay->fb_x;
- win_data->fb_y = overlay->fb_y;
- win_data->fb_width = overlay->fb_width;
- win_data->fb_height = overlay->fb_height;
- win_data->src_width = overlay->src_width;
- win_data->src_height = overlay->src_height;
-
- win_data->mode_width = overlay->mode_width;
- win_data->mode_height = overlay->mode_height;
-
- win_data->scan_flags = overlay->scan_flag;
-}
-
-static void mixer_win_commit(void *ctx, int win)
-{
- struct mixer_context *mixer_ctx = ctx;
-
- DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
-
- if (win > 1)
- vp_video_buffer(mixer_ctx, win);
- else
- mixer_graph_buffer(mixer_ctx, win);
-}
-
-static void mixer_win_disable(void *ctx, int win)
-{
- struct mixer_context *mixer_ctx = ctx;
- struct mixer_resources *res = &mixer_ctx->mixer_res;
- unsigned long flags;
-
- DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
-
- spin_lock_irqsave(&res->reg_slock, flags);
- mixer_vsync_set_update(mixer_ctx, false);
-
- mixer_cfg_layer(mixer_ctx, win, false);
-
- mixer_vsync_set_update(mixer_ctx, true);
- spin_unlock_irqrestore(&res->reg_slock, flags);
-}
-
-static struct exynos_mixer_ops mixer_ops = {
- /* manager */
- .enable_vblank = mixer_enable_vblank,
- .disable_vblank = mixer_disable_vblank,
- .dpms = mixer_dpms,
-
- /* overlay */
- .win_mode_set = mixer_win_mode_set,
- .win_commit = mixer_win_commit,
- .win_disable = mixer_win_disable,
-};
-
-/* for pageflip event */
-static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
-{
- struct exynos_drm_private *dev_priv = drm_dev->dev_private;
- struct drm_pending_vblank_event *e, *t;
- struct timeval now;
- unsigned long flags;
- bool is_checked = false;
-
- spin_lock_irqsave(&drm_dev->event_lock, flags);
-
- list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
- base.link) {
- /* if event's pipe isn't same as crtc then ignore it. */
- if (crtc != e->pipe)
- continue;
-
- is_checked = true;
- do_gettimeofday(&now);
- e->event.sequence = 0;
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
-
- list_move_tail(&e->base.link, &e->base.file_priv->event_list);
- wake_up_interruptible(&e->base.file_priv->event_wait);
- }
-
- if (is_checked)
- /*
- * call drm_vblank_put only in case that drm_vblank_get was
- * called.
- */
- if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
- drm_vblank_put(drm_dev, crtc);
-
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-}
-
-static irqreturn_t mixer_irq_handler(int irq, void *arg)
-{
- struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
- struct mixer_context *ctx = drm_hdmi_ctx->ctx;
- struct mixer_resources *res = &ctx->mixer_res;
- u32 val, base, shadow;
-
- spin_lock(&res->reg_slock);
-
- /* read interrupt status for handling and clearing flags for VSYNC */
- val = mixer_reg_read(res, MXR_INT_STATUS);
-
- /* handling VSYNC */
- if (val & MXR_INT_STATUS_VSYNC) {
- /* interlace scan need to check shadow register */
- if (ctx->interlace) {
- base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
- shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
- if (base != shadow)
- goto out;
-
- base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
- shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
- if (base != shadow)
- goto out;
- }
-
- drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
- mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
- }
-
-out:
- /* clear interrupts */
- if (~val & MXR_INT_EN_VSYNC) {
- /* vsync interrupt use different bit for read and clear */
- val &= ~MXR_INT_EN_VSYNC;
- val |= MXR_INT_CLEAR_VSYNC;
- }
- mixer_reg_write(res, MXR_INT_STATUS, val);
-
- spin_unlock(&res->reg_slock);
-
- return IRQ_HANDLED;
-}
-
-static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
- struct platform_device *pdev)
-{
- struct mixer_context *mixer_ctx = ctx->ctx;
- struct device *dev = &pdev->dev;
- struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
- struct resource *res;
- int ret;
-
- spin_lock_init(&mixer_res->reg_slock);
-
- mixer_res->mixer = clk_get(dev, "mixer");
- if (IS_ERR_OR_NULL(mixer_res->mixer)) {
- dev_err(dev, "failed to get clock 'mixer'\n");
- ret = -ENODEV;
- goto fail;
- }
- mixer_res->vp = clk_get(dev, "vp");
- if (IS_ERR_OR_NULL(mixer_res->vp)) {
- dev_err(dev, "failed to get clock 'vp'\n");
- ret = -ENODEV;
- goto fail;
- }
- mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
- if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
- dev_err(dev, "failed to get clock 'sclk_mixer'\n");
- ret = -ENODEV;
- goto fail;
- }
- mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
- if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
- dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
- ret = -ENODEV;
- goto fail;
- }
- mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
- if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
- dev_err(dev, "failed to get clock 'sclk_dac'\n");
- ret = -ENODEV;
- goto fail;
- }
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
- if (res == NULL) {
- dev_err(dev, "get memory resource failed.\n");
- ret = -ENXIO;
- goto fail;
- }
-
- clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
-
- mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
- if (mixer_res->mixer_regs == NULL) {
- dev_err(dev, "register mapping failed.\n");
- ret = -ENXIO;
- goto fail;
- }
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
- if (res == NULL) {
- dev_err(dev, "get memory resource failed.\n");
- ret = -ENXIO;
- goto fail_mixer_regs;
- }
-
- mixer_res->vp_regs = ioremap(res->start, resource_size(res));
- if (mixer_res->vp_regs == NULL) {
- dev_err(dev, "register mapping failed.\n");
- ret = -ENXIO;
- goto fail_mixer_regs;
- }
-
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
- if (res == NULL) {
- dev_err(dev, "get interrupt resource failed.\n");
- ret = -ENXIO;
- goto fail_vp_regs;
- }
-
- ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
- if (ret) {
- dev_err(dev, "request interrupt failed.\n");
- goto fail_vp_regs;
- }
- mixer_res->irq = res->start;
-
- return 0;
-
-fail_vp_regs:
- iounmap(mixer_res->vp_regs);
-
-fail_mixer_regs:
- iounmap(mixer_res->mixer_regs);
-
-fail:
- if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
- clk_put(mixer_res->sclk_dac);
- if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
- clk_put(mixer_res->sclk_hdmi);
- if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
- clk_put(mixer_res->sclk_mixer);
- if (!IS_ERR_OR_NULL(mixer_res->vp))
- clk_put(mixer_res->vp);
- if (!IS_ERR_OR_NULL(mixer_res->mixer))
- clk_put(mixer_res->mixer);
- return ret;
-}
-
-static void mixer_resources_cleanup(struct mixer_context *ctx)
-{
- struct mixer_resources *res = &ctx->mixer_res;
-
- free_irq(res->irq, ctx);
-
- iounmap(res->vp_regs);
- iounmap(res->mixer_regs);
-}
-
-static int __devinit mixer_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct exynos_drm_hdmi_context *drm_hdmi_ctx;
- struct mixer_context *ctx;
- int ret;
-
- dev_info(dev, "probe start\n");
-
- drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
- if (!drm_hdmi_ctx) {
- DRM_ERROR("failed to allocate common hdmi context.\n");
- return -ENOMEM;
- }
-
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx) {
- DRM_ERROR("failed to alloc mixer context.\n");
- kfree(drm_hdmi_ctx);
- return -ENOMEM;
- }
-
- mutex_init(&ctx->mixer_mutex);
-
- ctx->dev = &pdev->dev;
- drm_hdmi_ctx->ctx = (void *)ctx;
-
- platform_set_drvdata(pdev, drm_hdmi_ctx);
-
- /* acquire resources: regs, irqs, clocks */
- ret = mixer_resources_init(drm_hdmi_ctx, pdev);
- if (ret)
- goto fail;
-
- /* register specific callback point to common hdmi. */
- exynos_mixer_ops_register(&mixer_ops);
-
- pm_runtime_enable(dev);
-
- return 0;
-
-
-fail:
- dev_info(dev, "probe failed\n");
- return ret;
-}
-
-static int mixer_remove(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct exynos_drm_hdmi_context *drm_hdmi_ctx =
- platform_get_drvdata(pdev);
- struct mixer_context *ctx = drm_hdmi_ctx->ctx;
-
- dev_info(dev, "remove successful\n");
-
- pm_runtime_disable(&pdev->dev);
-
- mixer_resources_cleanup(ctx);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int mixer_suspend(struct device *dev)
-{
- struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
- struct mixer_context *ctx = drm_hdmi_ctx->ctx;
-
- mixer_poweroff(ctx);
-
- return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
-
-struct platform_driver mixer_driver = {
- .driver = {
- .name = "s5p-mixer",
- .owner = THIS_MODULE,
- .pm = &mixer_pm_ops,
- },
- .probe = mixer_probe,
- .remove = __devexit_p(mixer_remove),
-};
diff --git a/drivers/gpu/drm/exynos_tmp/regs-hdmi.h b/drivers/gpu/drm/exynos_tmp/regs-hdmi.h
deleted file mode 100644
index 93576a0..0000000
--- a/drivers/gpu/drm/exynos_tmp/regs-hdmi.h
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- *
- * Cloned from drivers/media/video/s5p-tv/regs-hdmi.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * HDMI register header file for Samsung TVOUT driver
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef SAMSUNG_REGS_HDMI_H
-#define SAMSUNG_REGS_HDMI_H
-
-/*
- * Register part
-*/
-
-/* HDMI Version 1.3 & Common */
-#define HDMI_CTRL_BASE(x) ((x) + 0x00000000)
-#define HDMI_CORE_BASE(x) ((x) + 0x00010000)
-#define HDMI_I2S_BASE(x) ((x) + 0x00040000)
-#define HDMI_TG_BASE(x) ((x) + 0x00050000)
-
-/* Control registers */
-#define HDMI_INTC_CON HDMI_CTRL_BASE(0x0000)
-#define HDMI_INTC_FLAG HDMI_CTRL_BASE(0x0004)
-#define HDMI_HPD_STATUS HDMI_CTRL_BASE(0x000C)
-#define HDMI_V13_PHY_RSTOUT HDMI_CTRL_BASE(0x0014)
-#define HDMI_V13_PHY_VPLL HDMI_CTRL_BASE(0x0018)
-#define HDMI_V13_PHY_CMU HDMI_CTRL_BASE(0x001C)
-#define HDMI_V13_CORE_RSTOUT HDMI_CTRL_BASE(0x0020)
-
-/* Core registers */
-#define HDMI_CON_0 HDMI_CORE_BASE(0x0000)
-#define HDMI_CON_1 HDMI_CORE_BASE(0x0004)
-#define HDMI_CON_2 HDMI_CORE_BASE(0x0008)
-#define HDMI_SYS_STATUS HDMI_CORE_BASE(0x0010)
-#define HDMI_V13_PHY_STATUS HDMI_CORE_BASE(0x0014)
-#define HDMI_STATUS_EN HDMI_CORE_BASE(0x0020)
-#define HDMI_HPD HDMI_CORE_BASE(0x0030)
-#define HDMI_MODE_SEL HDMI_CORE_BASE(0x0040)
-#define HDMI_ENC_EN HDMI_CORE_BASE(0x0044)
-#define HDMI_V13_BLUE_SCREEN_0 HDMI_CORE_BASE(0x0050)
-#define HDMI_V13_BLUE_SCREEN_1 HDMI_CORE_BASE(0x0054)
-#define HDMI_V13_BLUE_SCREEN_2 HDMI_CORE_BASE(0x0058)
-#define HDMI_H_BLANK_0 HDMI_CORE_BASE(0x00A0)
-#define HDMI_H_BLANK_1 HDMI_CORE_BASE(0x00A4)
-#define HDMI_V13_V_BLANK_0 HDMI_CORE_BASE(0x00B0)
-#define HDMI_V13_V_BLANK_1 HDMI_CORE_BASE(0x00B4)
-#define HDMI_V13_V_BLANK_2 HDMI_CORE_BASE(0x00B8)
-#define HDMI_V13_H_V_LINE_0 HDMI_CORE_BASE(0x00C0)
-#define HDMI_V13_H_V_LINE_1 HDMI_CORE_BASE(0x00C4)
-#define HDMI_V13_H_V_LINE_2 HDMI_CORE_BASE(0x00C8)
-#define HDMI_VSYNC_POL HDMI_CORE_BASE(0x00E4)
-#define HDMI_INT_PRO_MODE HDMI_CORE_BASE(0x00E8)
-#define HDMI_V13_V_BLANK_F_0 HDMI_CORE_BASE(0x0110)
-#define HDMI_V13_V_BLANK_F_1 HDMI_CORE_BASE(0x0114)
-#define HDMI_V13_V_BLANK_F_2 HDMI_CORE_BASE(0x0118)
-#define HDMI_V13_H_SYNC_GEN_0 HDMI_CORE_BASE(0x0120)
-#define HDMI_V13_H_SYNC_GEN_1 HDMI_CORE_BASE(0x0124)
-#define HDMI_V13_H_SYNC_GEN_2 HDMI_CORE_BASE(0x0128)
-#define HDMI_V13_V_SYNC_GEN_1_0 HDMI_CORE_BASE(0x0130)
-#define HDMI_V13_V_SYNC_GEN_1_1 HDMI_CORE_BASE(0x0134)
-#define HDMI_V13_V_SYNC_GEN_1_2 HDMI_CORE_BASE(0x0138)
-#define HDMI_V13_V_SYNC_GEN_2_0 HDMI_CORE_BASE(0x0140)
-#define HDMI_V13_V_SYNC_GEN_2_1 HDMI_CORE_BASE(0x0144)
-#define HDMI_V13_V_SYNC_GEN_2_2 HDMI_CORE_BASE(0x0148)
-#define HDMI_V13_V_SYNC_GEN_3_0 HDMI_CORE_BASE(0x0150)
-#define HDMI_V13_V_SYNC_GEN_3_1 HDMI_CORE_BASE(0x0154)
-#define HDMI_V13_V_SYNC_GEN_3_2 HDMI_CORE_BASE(0x0158)
-#define HDMI_V13_ACR_CON HDMI_CORE_BASE(0x0180)
-#define HDMI_V13_ACR_CTS0 HDMI_CORE_BASE(0x0190)
-#define HDMI_V13_AVI_CON HDMI_CORE_BASE(0x0300)
-#define HDMI_V13_AVI_BYTE(n) HDMI_CORE_BASE(0x0320 + 4 * (n))
-#define HDMI_V13_DC_CONTROL HDMI_CORE_BASE(0x05C0)
-#define HDMI_V13_VIDEO_PATTERN_GEN HDMI_CORE_BASE(0x05C4)
-#define HDMI_V13_HPD_GEN HDMI_CORE_BASE(0x05C8)
-#define HDMI_V13_AUI_CON HDMI_CORE_BASE(0x0360)
-#define HDMI_V13_SPD_CON HDMI_CORE_BASE(0x0400)
-
-/* Timing generator registers */
-#define HDMI_TG_CMD HDMI_TG_BASE(0x0000)
-#define HDMI_TG_H_FSZ_L HDMI_TG_BASE(0x0018)
-#define HDMI_TG_H_FSZ_H HDMI_TG_BASE(0x001C)
-#define HDMI_TG_HACT_ST_L HDMI_TG_BASE(0x0020)
-#define HDMI_TG_HACT_ST_H HDMI_TG_BASE(0x0024)
-#define HDMI_TG_HACT_SZ_L HDMI_TG_BASE(0x0028)
-#define HDMI_TG_HACT_SZ_H HDMI_TG_BASE(0x002C)
-#define HDMI_TG_V_FSZ_L HDMI_TG_BASE(0x0030)
-#define HDMI_TG_V_FSZ_H HDMI_TG_BASE(0x0034)
-#define HDMI_TG_VSYNC_L HDMI_TG_BASE(0x0038)
-#define HDMI_TG_VSYNC_H HDMI_TG_BASE(0x003C)
-#define HDMI_TG_VSYNC2_L HDMI_TG_BASE(0x0040)
-#define HDMI_TG_VSYNC2_H HDMI_TG_BASE(0x0044)
-#define HDMI_TG_VACT_ST_L HDMI_TG_BASE(0x0048)
-#define HDMI_TG_VACT_ST_H HDMI_TG_BASE(0x004C)
-#define HDMI_TG_VACT_SZ_L HDMI_TG_BASE(0x0050)
-#define HDMI_TG_VACT_SZ_H HDMI_TG_BASE(0x0054)
-#define HDMI_TG_FIELD_CHG_L HDMI_TG_BASE(0x0058)
-#define HDMI_TG_FIELD_CHG_H HDMI_TG_BASE(0x005C)
-#define HDMI_TG_VACT_ST2_L HDMI_TG_BASE(0x0060)
-#define HDMI_TG_VACT_ST2_H HDMI_TG_BASE(0x0064)
-#define HDMI_TG_VSYNC_TOP_HDMI_L HDMI_TG_BASE(0x0078)
-#define HDMI_TG_VSYNC_TOP_HDMI_H HDMI_TG_BASE(0x007C)
-#define HDMI_TG_VSYNC_BOT_HDMI_L HDMI_TG_BASE(0x0080)
-#define HDMI_TG_VSYNC_BOT_HDMI_H HDMI_TG_BASE(0x0084)
-#define HDMI_TG_FIELD_TOP_HDMI_L HDMI_TG_BASE(0x0088)
-#define HDMI_TG_FIELD_TOP_HDMI_H HDMI_TG_BASE(0x008C)
-#define HDMI_TG_FIELD_BOT_HDMI_L HDMI_TG_BASE(0x0090)
-#define HDMI_TG_FIELD_BOT_HDMI_H HDMI_TG_BASE(0x0094)
-
-/*
- * Bit definition part
- */
-
-/* HDMI_INTC_CON */
-#define HDMI_INTC_EN_GLOBAL (1 << 6)
-#define HDMI_INTC_EN_HPD_PLUG (1 << 3)
-#define HDMI_INTC_EN_HPD_UNPLUG (1 << 2)
-
-/* HDMI_INTC_FLAG */
-#define HDMI_INTC_FLAG_HPD_PLUG (1 << 3)
-#define HDMI_INTC_FLAG_HPD_UNPLUG (1 << 2)
-
-/* HDMI_PHY_RSTOUT */
-#define HDMI_PHY_SW_RSTOUT (1 << 0)
-
-/* HDMI_CORE_RSTOUT */
-#define HDMI_CORE_SW_RSTOUT (1 << 0)
-
-/* HDMI_CON_0 */
-#define HDMI_BLUE_SCR_EN (1 << 5)
-#define HDMI_ASP_EN (1 << 2)
-#define HDMI_ASP_DIS (0 << 2)
-#define HDMI_ASP_MASK (1 << 2)
-#define HDMI_EN (1 << 0)
-
-/* HDMI_CON_2 */
-#define HDMI_VID_PREAMBLE_DIS (1 << 5)
-#define HDMI_GUARD_BAND_DIS (1 << 1)
-
-/* HDMI_PHY_STATUS */
-#define HDMI_PHY_STATUS_READY (1 << 0)
-
-/* HDMI_MODE_SEL */
-#define HDMI_MODE_HDMI_EN (1 << 1)
-#define HDMI_MODE_DVI_EN (1 << 0)
-#define HDMI_MODE_MASK (3 << 0)
-
-/* HDMI_TG_CMD */
-#define HDMI_TG_EN (1 << 0)
-#define HDMI_FIELD_EN (1 << 1)
-
-
-/* HDMI Version 1.4 */
-/* Control registers */
-/* #define HDMI_INTC_CON HDMI_CTRL_BASE(0x0000) */
-/* #define HDMI_INTC_FLAG HDMI_CTRL_BASE(0x0004) */
-#define HDMI_HDCP_KEY_LOAD HDMI_CTRL_BASE(0x0008)
-/* #define HDMI_HPD_STATUS HDMI_CTRL_BASE(0x000C) */
-#define HDMI_INTC_CON_1 HDMI_CTRL_BASE(0x0010)
-#define HDMI_INTC_FLAG_1 HDMI_CTRL_BASE(0x0014)
-#define HDMI_PHY_STATUS_0 HDMI_CTRL_BASE(0x0020)
-#define HDMI_PHY_STATUS_CMU HDMI_CTRL_BASE(0x0024)
-#define HDMI_PHY_STATUS_PLL HDMI_CTRL_BASE(0x0028)
-#define HDMI_PHY_CON_0 HDMI_CTRL_BASE(0x0030)
-#define HDMI_HPD_CTRL HDMI_CTRL_BASE(0x0040)
-#define HDMI_HPD_ST HDMI_CTRL_BASE(0x0044)
-#define HDMI_HPD_TH_X HDMI_CTRL_BASE(0x0050)
-#define HDMI_AUDIO_CLKSEL HDMI_CTRL_BASE(0x0070)
-#define HDMI_PHY_RSTOUT HDMI_CTRL_BASE(0x0074)
-#define HDMI_PHY_VPLL HDMI_CTRL_BASE(0x0078)
-#define HDMI_PHY_CMU HDMI_CTRL_BASE(0x007C)
-#define HDMI_CORE_RSTOUT HDMI_CTRL_BASE(0x0080)
-
-/* Video related registers */
-#define HDMI_YMAX HDMI_CORE_BASE(0x0060)
-#define HDMI_YMIN HDMI_CORE_BASE(0x0064)
-#define HDMI_CMAX HDMI_CORE_BASE(0x0068)
-#define HDMI_CMIN HDMI_CORE_BASE(0x006C)
-
-#define HDMI_V2_BLANK_0 HDMI_CORE_BASE(0x00B0)
-#define HDMI_V2_BLANK_1 HDMI_CORE_BASE(0x00B4)
-#define HDMI_V1_BLANK_0 HDMI_CORE_BASE(0x00B8)
-#define HDMI_V1_BLANK_1 HDMI_CORE_BASE(0x00BC)
-
-#define HDMI_V_LINE_0 HDMI_CORE_BASE(0x00C0)
-#define HDMI_V_LINE_1 HDMI_CORE_BASE(0x00C4)
-#define HDMI_H_LINE_0 HDMI_CORE_BASE(0x00C8)
-#define HDMI_H_LINE_1 HDMI_CORE_BASE(0x00CC)
-
-#define HDMI_HSYNC_POL HDMI_CORE_BASE(0x00E0)
-
-#define HDMI_V_BLANK_F0_0 HDMI_CORE_BASE(0x0110)
-#define HDMI_V_BLANK_F0_1 HDMI_CORE_BASE(0x0114)
-#define HDMI_V_BLANK_F1_0 HDMI_CORE_BASE(0x0118)
-#define HDMI_V_BLANK_F1_1 HDMI_CORE_BASE(0x011C)
-
-#define HDMI_H_SYNC_START_0 HDMI_CORE_BASE(0x0120)
-#define HDMI_H_SYNC_START_1 HDMI_CORE_BASE(0x0124)
-#define HDMI_H_SYNC_END_0 HDMI_CORE_BASE(0x0128)
-#define HDMI_H_SYNC_END_1 HDMI_CORE_BASE(0x012C)
-
-#define HDMI_V_SYNC_LINE_BEF_2_0 HDMI_CORE_BASE(0x0130)
-#define HDMI_V_SYNC_LINE_BEF_2_1 HDMI_CORE_BASE(0x0134)
-#define HDMI_V_SYNC_LINE_BEF_1_0 HDMI_CORE_BASE(0x0138)
-#define HDMI_V_SYNC_LINE_BEF_1_1 HDMI_CORE_BASE(0x013C)
-
-#define HDMI_V_SYNC_LINE_AFT_2_0 HDMI_CORE_BASE(0x0140)
-#define HDMI_V_SYNC_LINE_AFT_2_1 HDMI_CORE_BASE(0x0144)
-#define HDMI_V_SYNC_LINE_AFT_1_0 HDMI_CORE_BASE(0x0148)
-#define HDMI_V_SYNC_LINE_AFT_1_1 HDMI_CORE_BASE(0x014C)
-
-#define HDMI_V_SYNC_LINE_AFT_PXL_2_0 HDMI_CORE_BASE(0x0150)
-#define HDMI_V_SYNC_LINE_AFT_PXL_2_1 HDMI_CORE_BASE(0x0154)
-#define HDMI_V_SYNC_LINE_AFT_PXL_1_0 HDMI_CORE_BASE(0x0158)
-#define HDMI_V_SYNC_LINE_AFT_PXL_1_1 HDMI_CORE_BASE(0x015C)
-
-#define HDMI_V_BLANK_F2_0 HDMI_CORE_BASE(0x0160)
-#define HDMI_V_BLANK_F2_1 HDMI_CORE_BASE(0x0164)
-#define HDMI_V_BLANK_F3_0 HDMI_CORE_BASE(0x0168)
-#define HDMI_V_BLANK_F3_1 HDMI_CORE_BASE(0x016C)
-#define HDMI_V_BLANK_F4_0 HDMI_CORE_BASE(0x0170)
-#define HDMI_V_BLANK_F4_1 HDMI_CORE_BASE(0x0174)
-#define HDMI_V_BLANK_F5_0 HDMI_CORE_BASE(0x0178)
-#define HDMI_V_BLANK_F5_1 HDMI_CORE_BASE(0x017C)
-
-#define HDMI_V_SYNC_LINE_AFT_3_0 HDMI_CORE_BASE(0x0180)
-#define HDMI_V_SYNC_LINE_AFT_3_1 HDMI_CORE_BASE(0x0184)
-#define HDMI_V_SYNC_LINE_AFT_4_0 HDMI_CORE_BASE(0x0188)
-#define HDMI_V_SYNC_LINE_AFT_4_1 HDMI_CORE_BASE(0x018C)
-#define HDMI_V_SYNC_LINE_AFT_5_0 HDMI_CORE_BASE(0x0190)
-#define HDMI_V_SYNC_LINE_AFT_5_1 HDMI_CORE_BASE(0x0194)
-#define HDMI_V_SYNC_LINE_AFT_6_0 HDMI_CORE_BASE(0x0198)
-#define HDMI_V_SYNC_LINE_AFT_6_1 HDMI_CORE_BASE(0x019C)
-
-#define HDMI_V_SYNC_LINE_AFT_PXL_3_0 HDMI_CORE_BASE(0x01A0)
-#define HDMI_V_SYNC_LINE_AFT_PXL_3_1 HDMI_CORE_BASE(0x01A4)
-#define HDMI_V_SYNC_LINE_AFT_PXL_4_0 HDMI_CORE_BASE(0x01A8)
-#define HDMI_V_SYNC_LINE_AFT_PXL_4_1 HDMI_CORE_BASE(0x01AC)
-#define HDMI_V_SYNC_LINE_AFT_PXL_5_0 HDMI_CORE_BASE(0x01B0)
-#define HDMI_V_SYNC_LINE_AFT_PXL_5_1 HDMI_CORE_BASE(0x01B4)
-#define HDMI_V_SYNC_LINE_AFT_PXL_6_0 HDMI_CORE_BASE(0x01B8)
-#define HDMI_V_SYNC_LINE_AFT_PXL_6_1 HDMI_CORE_BASE(0x01BC)
-
-#define HDMI_VACT_SPACE_1_0 HDMI_CORE_BASE(0x01C0)
-#define HDMI_VACT_SPACE_1_1 HDMI_CORE_BASE(0x01C4)
-#define HDMI_VACT_SPACE_2_0 HDMI_CORE_BASE(0x01C8)
-#define HDMI_VACT_SPACE_2_1 HDMI_CORE_BASE(0x01CC)
-#define HDMI_VACT_SPACE_3_0 HDMI_CORE_BASE(0x01D0)
-#define HDMI_VACT_SPACE_3_1 HDMI_CORE_BASE(0x01D4)
-#define HDMI_VACT_SPACE_4_0 HDMI_CORE_BASE(0x01D8)
-#define HDMI_VACT_SPACE_4_1 HDMI_CORE_BASE(0x01DC)
-#define HDMI_VACT_SPACE_5_0 HDMI_CORE_BASE(0x01E0)
-#define HDMI_VACT_SPACE_5_1 HDMI_CORE_BASE(0x01E4)
-#define HDMI_VACT_SPACE_6_0 HDMI_CORE_BASE(0x01E8)
-#define HDMI_VACT_SPACE_6_1 HDMI_CORE_BASE(0x01EC)
-
-#define HDMI_GCP_CON HDMI_CORE_BASE(0x0200)
-#define HDMI_GCP_BYTE1 HDMI_CORE_BASE(0x0210)
-#define HDMI_GCP_BYTE2 HDMI_CORE_BASE(0x0214)
-#define HDMI_GCP_BYTE3 HDMI_CORE_BASE(0x0218)
-
-/* Audio related registers */
-#define HDMI_ASP_CON HDMI_CORE_BASE(0x0300)
-#define HDMI_ASP_SP_FLAT HDMI_CORE_BASE(0x0304)
-#define HDMI_ASP_CHCFG0 HDMI_CORE_BASE(0x0310)
-#define HDMI_ASP_CHCFG1 HDMI_CORE_BASE(0x0314)
-#define HDMI_ASP_CHCFG2 HDMI_CORE_BASE(0x0318)
-#define HDMI_ASP_CHCFG3 HDMI_CORE_BASE(0x031C)
-
-#define HDMI_ACR_CON HDMI_CORE_BASE(0x0400)
-#define HDMI_ACR_MCTS0 HDMI_CORE_BASE(0x0410)
-#define HDMI_ACR_MCTS1 HDMI_CORE_BASE(0x0414)
-#define HDMI_ACR_MCTS2 HDMI_CORE_BASE(0x0418)
-#define HDMI_ACR_CTS0 HDMI_CORE_BASE(0x0420)
-#define HDMI_ACR_CTS1 HDMI_CORE_BASE(0x0424)
-#define HDMI_ACR_CTS2 HDMI_CORE_BASE(0x0428)
-#define HDMI_ACR_N0 HDMI_CORE_BASE(0x0430)
-#define HDMI_ACR_N1 HDMI_CORE_BASE(0x0434)
-#define HDMI_ACR_N2 HDMI_CORE_BASE(0x0438)
-
-/* Packet related registers */
-#define HDMI_ACP_CON HDMI_CORE_BASE(0x0500)
-#define HDMI_ACP_TYPE HDMI_CORE_BASE(0x0514)
-#define HDMI_ACP_DATA(n) HDMI_CORE_BASE(0x0520 + 4 * (n))
-
-#define HDMI_ISRC_CON HDMI_CORE_BASE(0x0600)
-#define HDMI_ISRC1_HEADER1 HDMI_CORE_BASE(0x0614)
-#define HDMI_ISRC1_DATA(n) HDMI_CORE_BASE(0x0620 + 4 * (n))
-#define HDMI_ISRC2_DATA(n) HDMI_CORE_BASE(0x06A0 + 4 * (n))
-
-#define HDMI_AVI_CON HDMI_CORE_BASE(0x0700)
-#define HDMI_AVI_HEADER0 HDMI_CORE_BASE(0x0710)
-#define HDMI_AVI_HEADER1 HDMI_CORE_BASE(0x0714)
-#define HDMI_AVI_HEADER2 HDMI_CORE_BASE(0x0718)
-#define HDMI_AVI_CHECK_SUM HDMI_CORE_BASE(0x071C)
-#define HDMI_AVI_BYTE(n) HDMI_CORE_BASE(0x0720 + 4 * (n))
-
-#define HDMI_AUI_CON HDMI_CORE_BASE(0x0800)
-#define HDMI_AUI_HEADER0 HDMI_CORE_BASE(0x0810)
-#define HDMI_AUI_HEADER1 HDMI_CORE_BASE(0x0814)
-#define HDMI_AUI_HEADER2 HDMI_CORE_BASE(0x0818)
-#define HDMI_AUI_CHECK_SUM HDMI_CORE_BASE(0x081C)
-#define HDMI_AUI_BYTE(n) HDMI_CORE_BASE(0x0820 + 4 * (n))
-
-#define HDMI_MPG_CON HDMI_CORE_BASE(0x0900)
-#define HDMI_MPG_CHECK_SUM HDMI_CORE_BASE(0x091C)
-#define HDMI_MPG_DATA(n) HDMI_CORE_BASE(0x0920 + 4 * (n))
-
-#define HDMI_SPD_CON HDMI_CORE_BASE(0x0A00)
-#define HDMI_SPD_HEADER0 HDMI_CORE_BASE(0x0A10)
-#define HDMI_SPD_HEADER1 HDMI_CORE_BASE(0x0A14)
-#define HDMI_SPD_HEADER2 HDMI_CORE_BASE(0x0A18)
-#define HDMI_SPD_DATA(n) HDMI_CORE_BASE(0x0A20 + 4 * (n))
-
-#define HDMI_GAMUT_CON HDMI_CORE_BASE(0x0B00)
-#define HDMI_GAMUT_HEADER0 HDMI_CORE_BASE(0x0B10)
-#define HDMI_GAMUT_HEADER1 HDMI_CORE_BASE(0x0B14)
-#define HDMI_GAMUT_HEADER2 HDMI_CORE_BASE(0x0B18)
-#define HDMI_GAMUT_METADATA(n) HDMI_CORE_BASE(0x0B20 + 4 * (n))
-
-#define HDMI_VSI_CON HDMI_CORE_BASE(0x0C00)
-#define HDMI_VSI_HEADER0 HDMI_CORE_BASE(0x0C10)
-#define HDMI_VSI_HEADER1 HDMI_CORE_BASE(0x0C14)
-#define HDMI_VSI_HEADER2 HDMI_CORE_BASE(0x0C18)
-#define HDMI_VSI_DATA(n) HDMI_CORE_BASE(0x0C20 + 4 * (n))
-
-#define HDMI_DC_CONTROL HDMI_CORE_BASE(0x0D00)
-#define HDMI_VIDEO_PATTERN_GEN HDMI_CORE_BASE(0x0D04)
-
-#define HDMI_AN_SEED_SEL HDMI_CORE_BASE(0x0E48)
-#define HDMI_AN_SEED_0 HDMI_CORE_BASE(0x0E58)
-#define HDMI_AN_SEED_1 HDMI_CORE_BASE(0x0E5C)
-#define HDMI_AN_SEED_2 HDMI_CORE_BASE(0x0E60)
-#define HDMI_AN_SEED_3 HDMI_CORE_BASE(0x0E64)
-
-/* HDCP related registers */
-#define HDMI_HDCP_SHA1(n) HDMI_CORE_BASE(0x7000 + 4 * (n))
-#define HDMI_HDCP_KSV_LIST(n) HDMI_CORE_BASE(0x7050 + 4 * (n))
-
-#define HDMI_HDCP_KSV_LIST_CON HDMI_CORE_BASE(0x7064)
-#define HDMI_HDCP_SHA_RESULT HDMI_CORE_BASE(0x7070)
-#define HDMI_HDCP_CTRL1 HDMI_CORE_BASE(0x7080)
-#define HDMI_HDCP_CTRL2 HDMI_CORE_BASE(0x7084)
-#define HDMI_HDCP_CHECK_RESULT HDMI_CORE_BASE(0x7090)
-#define HDMI_HDCP_BKSV(n) HDMI_CORE_BASE(0x70A0 + 4 * (n))
-#define HDMI_HDCP_AKSV(n) HDMI_CORE_BASE(0x70C0 + 4 * (n))
-#define HDMI_HDCP_AN(n) HDMI_CORE_BASE(0x70E0 + 4 * (n))
-
-#define HDMI_HDCP_BCAPS HDMI_CORE_BASE(0x7100)
-#define HDMI_HDCP_BSTATUS_0 HDMI_CORE_BASE(0x7110)
-#define HDMI_HDCP_BSTATUS_1 HDMI_CORE_BASE(0x7114)
-#define HDMI_HDCP_RI_0 HDMI_CORE_BASE(0x7140)
-#define HDMI_HDCP_RI_1 HDMI_CORE_BASE(0x7144)
-#define HDMI_HDCP_I2C_INT HDMI_CORE_BASE(0x7180)
-#define HDMI_HDCP_AN_INT HDMI_CORE_BASE(0x7190)
-#define HDMI_HDCP_WDT_INT HDMI_CORE_BASE(0x71A0)
-#define HDMI_HDCP_RI_INT HDMI_CORE_BASE(0x71B0)
-#define HDMI_HDCP_RI_COMPARE_0 HDMI_CORE_BASE(0x71D0)
-#define HDMI_HDCP_RI_COMPARE_1 HDMI_CORE_BASE(0x71D4)
-#define HDMI_HDCP_FRAME_COUNT HDMI_CORE_BASE(0x71E0)
-
-#define HDMI_RGB_ROUND_EN HDMI_CORE_BASE(0xD500)
-#define HDMI_VACT_SPACE_R_0 HDMI_CORE_BASE(0xD504)
-#define HDMI_VACT_SPACE_R_1 HDMI_CORE_BASE(0xD508)
-#define HDMI_VACT_SPACE_G_0 HDMI_CORE_BASE(0xD50C)
-#define HDMI_VACT_SPACE_G_1 HDMI_CORE_BASE(0xD510)
-#define HDMI_VACT_SPACE_B_0 HDMI_CORE_BASE(0xD514)
-#define HDMI_VACT_SPACE_B_1 HDMI_CORE_BASE(0xD518)
-
-#define HDMI_BLUE_SCREEN_B_0 HDMI_CORE_BASE(0xD520)
-#define HDMI_BLUE_SCREEN_B_1 HDMI_CORE_BASE(0xD524)
-#define HDMI_BLUE_SCREEN_G_0 HDMI_CORE_BASE(0xD528)
-#define HDMI_BLUE_SCREEN_G_1 HDMI_CORE_BASE(0xD52C)
-#define HDMI_BLUE_SCREEN_R_0 HDMI_CORE_BASE(0xD530)
-#define HDMI_BLUE_SCREEN_R_1 HDMI_CORE_BASE(0xD534)
-
-/* HDMI I2S register */
-#define HDMI_I2S_CLK_CON HDMI_I2S_BASE(0x000)
-#define HDMI_I2S_CON_1 HDMI_I2S_BASE(0x004)
-#define HDMI_I2S_CON_2 HDMI_I2S_BASE(0x008)
-#define HDMI_I2S_PIN_SEL_0 HDMI_I2S_BASE(0x00c)
-#define HDMI_I2S_PIN_SEL_1 HDMI_I2S_BASE(0x010)
-#define HDMI_I2S_PIN_SEL_2 HDMI_I2S_BASE(0x014)
-#define HDMI_I2S_PIN_SEL_3 HDMI_I2S_BASE(0x018)
-#define HDMI_I2S_DSD_CON HDMI_I2S_BASE(0x01c)
-#define HDMI_I2S_MUX_CON HDMI_I2S_BASE(0x020)
-#define HDMI_I2S_CH_ST_CON HDMI_I2S_BASE(0x024)
-#define HDMI_I2S_CH_ST_0 HDMI_I2S_BASE(0x028)
-#define HDMI_I2S_CH_ST_1 HDMI_I2S_BASE(0x02c)
-#define HDMI_I2S_CH_ST_2 HDMI_I2S_BASE(0x030)
-#define HDMI_I2S_CH_ST_3 HDMI_I2S_BASE(0x034)
-#define HDMI_I2S_CH_ST_4 HDMI_I2S_BASE(0x038)
-#define HDMI_I2S_CH_ST_SH_0 HDMI_I2S_BASE(0x03c)
-#define HDMI_I2S_CH_ST_SH_1 HDMI_I2S_BASE(0x040)
-#define HDMI_I2S_CH_ST_SH_2 HDMI_I2S_BASE(0x044)
-#define HDMI_I2S_CH_ST_SH_3 HDMI_I2S_BASE(0x048)
-#define HDMI_I2S_CH_ST_SH_4 HDMI_I2S_BASE(0x04c)
-#define HDMI_I2S_VD_DATA HDMI_I2S_BASE(0x050)
-#define HDMI_I2S_MUX_CH HDMI_I2S_BASE(0x054)
-#define HDMI_I2S_MUX_CUV HDMI_I2S_BASE(0x058)
-#define HDMI_I2S_IRQ_MASK HDMI_I2S_BASE(0x05c)
-#define HDMI_I2S_IRQ_STATUS HDMI_I2S_BASE(0x060)
-
-/* I2S bit definition */
-
-/* I2S_CLK_CON */
-#define HDMI_I2S_CLK_DIS (0)
-#define HDMI_I2S_CLK_EN (1)
-
-/* I2S_CON_1 */
-#define HDMI_I2S_SCLK_FALLING_EDGE (0 << 1)
-#define HDMI_I2S_SCLK_RISING_EDGE (1 << 1)
-#define HDMI_I2S_L_CH_LOW_POL (0)
-#define HDMI_I2S_L_CH_HIGH_POL (1)
-
-/* I2S_CON_2 */
-#define HDMI_I2S_MSB_FIRST_MODE (0 << 6)
-#define HDMI_I2S_LSB_FIRST_MODE (1 << 6)
-#define HDMI_I2S_BIT_CH_32FS (0 << 4)
-#define HDMI_I2S_BIT_CH_48FS (1 << 4)
-#define HDMI_I2S_BIT_CH_RESERVED (2 << 4)
-#define HDMI_I2S_SDATA_16BIT (1 << 2)
-#define HDMI_I2S_SDATA_20BIT (2 << 2)
-#define HDMI_I2S_SDATA_24BIT (3 << 2)
-#define HDMI_I2S_BASIC_FORMAT (0)
-#define HDMI_I2S_L_JUST_FORMAT (2)
-#define HDMI_I2S_R_JUST_FORMAT (3)
-#define HDMI_I2S_CON_2_CLR (~(0xFF))
-#define HDMI_I2S_SET_BIT_CH(x) (((x) & 0x7) << 4)
-#define HDMI_I2S_SET_SDATA_BIT(x) (((x) & 0x7) << 2)
-
-/* I2S_PIN_SEL_0 */
-#define HDMI_I2S_SEL_SCLK(x) (((x) & 0x7) << 4)
-#define HDMI_I2S_SEL_SCLK_DEFAULT_1 (0x7 << 4)
-#define HDMI_I2S_SEL_LRCK(x) ((x) & 0x7)
-#define HDMI_I2S_SEL_LRCK_DEFAULT_0 (0x7)
-
-/* I2S_PIN_SEL_1 */
-#define HDMI_I2S_SEL_SDATA1(x) (((x) & 0x7) << 4)
-#define HDMI_I2S_SEL_SDATA1_DEFAULT_3 (0x7 << 4)
-#define HDMI_I2S_SEL_SDATA2(x) ((x) & 0x7)
-#define HDMI_I2S_SEL_SDATA2_DEFAULT_2 (0x7)
-
-/* I2S_PIN_SEL_2 */
-#define HDMI_I2S_SEL_SDATA3(x) (((x) & 0x7) << 4)
-#define HDMI_I2S_SEL_SDATA3_DEFAULT_5 (0x7 << 4)
-#define HDMI_I2S_SEL_SDATA2(x) ((x) & 0x7)
-#define HDMI_I2S_SEL_SDATA2_DEFAULT_4 (0x7)
-
-/* I2S_PIN_SEL_3 */
-#define HDMI_I2S_SEL_DSD(x) ((x) & 0x7)
-#define HDMI_I2S_SEL_DSD_DEFAULT_6 (0x7)
-
-/* I2S_DSD_CON */
-#define HDMI_I2S_DSD_CLK_RI_EDGE (1 << 1)
-#define HDMI_I2S_DSD_CLK_FA_EDGE (0 << 1)
-#define HDMI_I2S_DSD_ENABLE (1)
-#define HDMI_I2S_DSD_DISABLE (0)
-
-/* I2S_MUX_CON */
-#define HDMI_I2S_NOISE_FILTER_ZERO (0 << 5)
-#define HDMI_I2S_NOISE_FILTER_2_STAGE (1 << 5)
-#define HDMI_I2S_NOISE_FILTER_3_STAGE (2 << 5)
-#define HDMI_I2S_NOISE_FILTER_4_STAGE (3 << 5)
-#define HDMI_I2S_NOISE_FILTER_5_STAGE (4 << 5)
-#define HDMI_I2S_IN_DISABLE (1 << 4)
-#define HDMI_I2S_IN_ENABLE (0 << 4)
-#define HDMI_I2S_AUD_SPDIF (0 << 2)
-#define HDMI_I2S_AUD_I2S (1 << 2)
-#define HDMI_I2S_AUD_DSD (2 << 2)
-#define HDMI_I2S_CUV_SPDIF_ENABLE (0 << 1)
-#define HDMI_I2S_CUV_I2S_ENABLE (1 << 1)
-#define HDMI_I2S_MUX_DISABLE (0)
-#define HDMI_I2S_MUX_ENABLE (1)
-#define HDMI_I2S_MUX_CON_CLR (~(0xFF))
-
-/* I2S_CH_ST_CON */
-#define HDMI_I2S_CH_STATUS_RELOAD (1)
-#define HDMI_I2S_CH_ST_CON_CLR (~(1))
-
-/* I2S_CH_ST_0 / I2S_CH_ST_SH_0 */
-#define HDMI_I2S_CH_STATUS_MODE_0 (0 << 6)
-#define HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH (0 << 3)
-#define HDMI_I2S_2AUD_CH_WITH_PREEMPH (1 << 3)
-#define HDMI_I2S_DEFAULT_EMPHASIS (0 << 3)
-#define HDMI_I2S_COPYRIGHT (0 << 2)
-#define HDMI_I2S_NO_COPYRIGHT (1 << 2)
-#define HDMI_I2S_LINEAR_PCM (0 << 1)
-#define HDMI_I2S_NO_LINEAR_PCM (1 << 1)
-#define HDMI_I2S_CONSUMER_FORMAT (0)
-#define HDMI_I2S_PROF_FORMAT (1)
-#define HDMI_I2S_CH_ST_0_CLR (~(0xFF))
-
-/* I2S_CH_ST_1 / I2S_CH_ST_SH_1 */
-#define HDMI_I2S_CD_PLAYER (0x00)
-#define HDMI_I2S_DAT_PLAYER (0x03)
-#define HDMI_I2S_DCC_PLAYER (0x43)
-#define HDMI_I2S_MINI_DISC_PLAYER (0x49)
-
-/* I2S_CH_ST_2 / I2S_CH_ST_SH_2 */
-#define HDMI_I2S_CHANNEL_NUM_MASK (0xF << 4)
-#define HDMI_I2S_SOURCE_NUM_MASK (0xF)
-#define HDMI_I2S_SET_CHANNEL_NUM(x) (((x) & (0xF)) << 4)
-#define HDMI_I2S_SET_SOURCE_NUM(x) ((x) & (0xF))
-
-/* I2S_CH_ST_3 / I2S_CH_ST_SH_3 */
-#define HDMI_I2S_CLK_ACCUR_LEVEL_1 (1 << 4)
-#define HDMI_I2S_CLK_ACCUR_LEVEL_2 (0 << 4)
-#define HDMI_I2S_CLK_ACCUR_LEVEL_3 (2 << 4)
-#define HDMI_I2S_SMP_FREQ_44_1 (0x0)
-#define HDMI_I2S_SMP_FREQ_48 (0x2)
-#define HDMI_I2S_SMP_FREQ_32 (0x3)
-#define HDMI_I2S_SMP_FREQ_96 (0xA)
-#define HDMI_I2S_SET_SMP_FREQ(x) ((x) & (0xF))
-
-/* I2S_CH_ST_4 / I2S_CH_ST_SH_4 */
-#define HDMI_I2S_ORG_SMP_FREQ_44_1 (0xF << 4)
-#define HDMI_I2S_ORG_SMP_FREQ_88_2 (0x7 << 4)
-#define HDMI_I2S_ORG_SMP_FREQ_22_05 (0xB << 4)
-#define HDMI_I2S_ORG_SMP_FREQ_176_4 (0x3 << 4)
-#define HDMI_I2S_WORD_LEN_NOT_DEFINE (0x0 << 1)
-#define HDMI_I2S_WORD_LEN_MAX24_20BITS (0x1 << 1)
-#define HDMI_I2S_WORD_LEN_MAX24_22BITS (0x2 << 1)
-#define HDMI_I2S_WORD_LEN_MAX24_23BITS (0x4 << 1)
-#define HDMI_I2S_WORD_LEN_MAX24_24BITS (0x5 << 1)
-#define HDMI_I2S_WORD_LEN_MAX24_21BITS (0x6 << 1)
-#define HDMI_I2S_WORD_LEN_MAX20_16BITS (0x1 << 1)
-#define HDMI_I2S_WORD_LEN_MAX20_18BITS (0x2 << 1)
-#define HDMI_I2S_WORD_LEN_MAX20_19BITS (0x4 << 1)
-#define HDMI_I2S_WORD_LEN_MAX20_20BITS (0x5 << 1)
-#define HDMI_I2S_WORD_LEN_MAX20_17BITS (0x6 << 1)
-#define HDMI_I2S_WORD_LEN_MAX_24BITS (1)
-#define HDMI_I2S_WORD_LEN_MAX_20BITS (0)
-
-/* I2S_VD_DATA */
-#define HDMI_I2S_VD_AUD_SMP_RELIABLE (0)
-#define HDMI_I2S_VD_AUD_SMP_UNRELIABLE (1)
-
-/* I2S_MUX_CH */
-#define HDMI_I2S_CH3_R_EN (1 << 7)
-#define HDMI_I2S_CH3_L_EN (1 << 6)
-#define HDMI_I2S_CH3_EN (3 << 6)
-#define HDMI_I2S_CH2_R_EN (1 << 5)
-#define HDMI_I2S_CH2_L_EN (1 << 4)
-#define HDMI_I2S_CH2_EN (3 << 4)
-#define HDMI_I2S_CH1_R_EN (1 << 3)
-#define HDMI_I2S_CH1_L_EN (1 << 2)
-#define HDMI_I2S_CH1_EN (3 << 2)
-#define HDMI_I2S_CH0_R_EN (1 << 1)
-#define HDMI_I2S_CH0_L_EN (1)
-#define HDMI_I2S_CH0_EN (3)
-#define HDMI_I2S_CH_ALL_EN (0xFF)
-#define HDMI_I2S_MUX_CH_CLR (~HDMI_I2S_CH_ALL_EN)
-
-/* I2S_MUX_CUV */
-#define HDMI_I2S_CUV_R_EN (1 << 1)
-#define HDMI_I2S_CUV_L_EN (1)
-#define HDMI_I2S_CUV_RL_EN (0x03)
-
-/* I2S_IRQ_MASK */
-#define HDMI_I2S_INT2_DIS (0 << 1)
-#define HDMI_I2S_INT2_EN (1 << 1)
-
-/* I2S_IRQ_STATUS */
-#define HDMI_I2S_INT2_STATUS (1 << 1)
-
-/* I2S_CUV_L_R */
-#define HDMI_I2S_CUV_R_DATA_MASK (0x7 << 4)
-#define HDMI_I2S_CUV_L_DATA_MASK (0x7)
-
-/* Audio Related Packet bit definition */
-
-/* ASP_CON */
-#define HDMI_AUD_DST_DOUBLE (1 << 7)
-#define HDMI_AUD_NO_DST_DOUBLE (0 << 7)
-#define HDMI_AUD_TYPE_SAMPLE (0 << 5)
-#define HDMI_AUD_TYPE_ONE_BIT (1 << 5)
-#define HDMI_AUD_TYPE_HBR (2 << 5)
-#define HDMI_AUD_TYPE_DST (3 << 5)
-#define HDMI_AUD_MODE_TWO_CH (0 << 4)
-#define HDMI_AUD_MODE_MULTI_CH (1 << 4)
-#define HDMI_AUD_SP_AUD3_EN (1 << 3)
-#define HDMI_AUD_SP_AUD2_EN (1 << 2)
-#define HDMI_AUD_SP_AUD1_EN (1 << 1)
-#define HDMI_AUD_SP_AUD0_EN (1 << 0)
-#define HDMI_AUD_SP_ALL_DIS (0 << 0)
-
-#define HDMI_AUD_SET_SP_PRE(x) ((x) & 0xF)
-
-/* ASP_SP_FLAT */
-#define HDMI_ASP_SP_FLAT_AUD_SAMPLE (0)
-
-/* ASP_CHCFG0/1/2/3 */
-#define HDMI_SPK3R_SEL_I_PCM0L (0 << 27)
-#define HDMI_SPK3R_SEL_I_PCM0R (1 << 27)
-#define HDMI_SPK3R_SEL_I_PCM1L (2 << 27)
-#define HDMI_SPK3R_SEL_I_PCM1R (3 << 27)
-#define HDMI_SPK3R_SEL_I_PCM2L (4 << 27)
-#define HDMI_SPK3R_SEL_I_PCM2R (5 << 27)
-#define HDMI_SPK3R_SEL_I_PCM3L (6 << 27)
-#define HDMI_SPK3R_SEL_I_PCM3R (7 << 27)
-#define HDMI_SPK3L_SEL_I_PCM0L (0 << 24)
-#define HDMI_SPK3L_SEL_I_PCM0R (1 << 24)
-#define HDMI_SPK3L_SEL_I_PCM1L (2 << 24)
-#define HDMI_SPK3L_SEL_I_PCM1R (3 << 24)
-#define HDMI_SPK3L_SEL_I_PCM2L (4 << 24)
-#define HDMI_SPK3L_SEL_I_PCM2R (5 << 24)
-#define HDMI_SPK3L_SEL_I_PCM3L (6 << 24)
-#define HDMI_SPK3L_SEL_I_PCM3R (7 << 24)
-#define HDMI_SPK2R_SEL_I_PCM0L (0 << 19)
-#define HDMI_SPK2R_SEL_I_PCM0R (1 << 19)
-#define HDMI_SPK2R_SEL_I_PCM1L (2 << 19)
-#define HDMI_SPK2R_SEL_I_PCM1R (3 << 19)
-#define HDMI_SPK2R_SEL_I_PCM2L (4 << 19)
-#define HDMI_SPK2R_SEL_I_PCM2R (5 << 19)
-#define HDMI_SPK2R_SEL_I_PCM3L (6 << 19)
-#define HDMI_SPK2R_SEL_I_PCM3R (7 << 19)
-#define HDMI_SPK2L_SEL_I_PCM0L (0 << 16)
-#define HDMI_SPK2L_SEL_I_PCM0R (1 << 16)
-#define HDMI_SPK2L_SEL_I_PCM1L (2 << 16)
-#define HDMI_SPK2L_SEL_I_PCM1R (3 << 16)
-#define HDMI_SPK2L_SEL_I_PCM2L (4 << 16)
-#define HDMI_SPK2L_SEL_I_PCM2R (5 << 16)
-#define HDMI_SPK2L_SEL_I_PCM3L (6 << 16)
-#define HDMI_SPK2L_SEL_I_PCM3R (7 << 16)
-#define HDMI_SPK1R_SEL_I_PCM0L (0 << 11)
-#define HDMI_SPK1R_SEL_I_PCM0R (1 << 11)
-#define HDMI_SPK1R_SEL_I_PCM1L (2 << 11)
-#define HDMI_SPK1R_SEL_I_PCM1R (3 << 11)
-#define HDMI_SPK1R_SEL_I_PCM2L (4 << 11)
-#define HDMI_SPK1R_SEL_I_PCM2R (5 << 11)
-#define HDMI_SPK1R_SEL_I_PCM3L (6 << 11)
-#define HDMI_SPK1R_SEL_I_PCM3R (7 << 11)
-#define HDMI_SPK1L_SEL_I_PCM0L (0 << 8)
-#define HDMI_SPK1L_SEL_I_PCM0R (1 << 8)
-#define HDMI_SPK1L_SEL_I_PCM1L (2 << 8)
-#define HDMI_SPK1L_SEL_I_PCM1R (3 << 8)
-#define HDMI_SPK1L_SEL_I_PCM2L (4 << 8)
-#define HDMI_SPK1L_SEL_I_PCM2R (5 << 8)
-#define HDMI_SPK1L_SEL_I_PCM3L (6 << 8)
-#define HDMI_SPK1L_SEL_I_PCM3R (7 << 8)
-#define HDMI_SPK0R_SEL_I_PCM0L (0 << 3)
-#define HDMI_SPK0R_SEL_I_PCM0R (1 << 3)
-#define HDMI_SPK0R_SEL_I_PCM1L (2 << 3)
-#define HDMI_SPK0R_SEL_I_PCM1R (3 << 3)
-#define HDMI_SPK0R_SEL_I_PCM2L (4 << 3)
-#define HDMI_SPK0R_SEL_I_PCM2R (5 << 3)
-#define HDMI_SPK0R_SEL_I_PCM3L (6 << 3)
-#define HDMI_SPK0R_SEL_I_PCM3R (7 << 3)
-#define HDMI_SPK0L_SEL_I_PCM0L (0)
-#define HDMI_SPK0L_SEL_I_PCM0R (1)
-#define HDMI_SPK0L_SEL_I_PCM1L (2)
-#define HDMI_SPK0L_SEL_I_PCM1R (3)
-#define HDMI_SPK0L_SEL_I_PCM2L (4)
-#define HDMI_SPK0L_SEL_I_PCM2R (5)
-#define HDMI_SPK0L_SEL_I_PCM3L (6)
-#define HDMI_SPK0L_SEL_I_PCM3R (7)
-
-/* ACR_CON */
-#define HDMI_ALT_CTS_RATE_CTS_1 (0 << 3)
-#define HDMI_ALT_CTS_RATE_CTS_11 (1 << 3)
-#define HDMI_ALT_CTS_RATE_CTS_21 (2 << 3)
-#define HDMI_ALT_CTS_RATE_CTS_31 (3 << 3)
-#define HDMI_ACR_TX_MODE_NO_TX (0)
-#define HDMI_ACR_TX_MODE_TX_ONCE (1)
-#define HDMI_ACR_TX_MODE_TXCNT_VBI (2)
-#define HDMI_ACR_TX_MODE_TX_VPC (3)
-#define HDMI_ACR_TX_MODE_MESURE_CTS (4)
-
-/* ACR_MCTS0/1/2 */
-
-/* ACR_CTS0/1/2 */
-
-/* ACR_N0/1/2 */
-
-/* ACR_LSB2 */
-#define HDMI_ACR_LSB2_MASK (0xFF)
-
-/* ACR_TXCNT */
-#define HDMI_ACR_TXCNT_MASK (0x1F)
-
-/* ACR_TXINTERNAL */
-#define HDMI_ACR_TX_INTERNAL_MASK (0xFF)
-
-/* ACR_CTS_OFFSET */
-#define HDMI_ACR_CTS_OFFSET_MASK (0xFF)
-
-/* GCP_CON */
-#define HDMI_GCP_CON_EN_1ST_VSYNC (1 << 3)
-#define HDMI_GCP_CON_EN_2ST_VSYNC (1 << 2)
-#define HDMI_GCP_CON_TRANS_EVERY_VSYNC (2)
-#define HDMI_GCP_CON_NO_TRAN (0)
-#define HDMI_GCP_CON_TRANS_ONCE (1)
-#define HDMI_GCP_CON_TRANS_EVERY_VSYNC (2)
-
-/* GCP_BYTE1 */
-#define HDMI_GCP_BYTE1_MASK (0xFF)
-
-/* GCP_BYTE2 */
-#define HDMI_GCP_BYTE2_PP_MASK (0xF << 4)
-#define HDMI_GCP_24BPP (1 << 2)
-#define HDMI_GCP_30BPP (1 << 0 | 1 << 2)
-#define HDMI_GCP_36BPP (1 << 1 | 1 << 2)
-#define HDMI_GCP_48BPP (1 << 0 | 1 << 1 | 1 << 2)
-
-/* GCP_BYTE3 */
-#define HDMI_GCP_BYTE3_MASK (0xFF)
-
-/* Timing generator registers */
-/* TG configure/status registers */
-#define HDMI_TG_VACT_ST3_L HDMI_TG_BASE(0x0068)
-#define HDMI_TG_VACT_ST3_H HDMI_TG_BASE(0x006c)
-#define HDMI_TG_VACT_ST4_L HDMI_TG_BASE(0x0070)
-#define HDMI_TG_VACT_ST4_H HDMI_TG_BASE(0x0074)
-#define HDMI_TG_3D HDMI_TG_BASE(0x00F0)
-
-#endif /* SAMSUNG_REGS_HDMI_H */
diff --git a/drivers/gpu/drm/exynos_tmp/regs-mixer.h b/drivers/gpu/drm/exynos_tmp/regs-mixer.h
deleted file mode 100644
index fd2f4d1..0000000
--- a/drivers/gpu/drm/exynos_tmp/regs-mixer.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *
- * Cloned from drivers/media/video/s5p-tv/regs-mixer.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Mixer register header file for Samsung Mixer driver
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-#ifndef SAMSUNG_REGS_MIXER_H
-#define SAMSUNG_REGS_MIXER_H
-
-/*
- * Register part
- */
-#define MXR_STATUS 0x0000
-#define MXR_CFG 0x0004
-#define MXR_INT_EN 0x0008
-#define MXR_INT_STATUS 0x000C
-#define MXR_LAYER_CFG 0x0010
-#define MXR_VIDEO_CFG 0x0014
-#define MXR_GRAPHIC0_CFG 0x0020
-#define MXR_GRAPHIC0_BASE 0x0024
-#define MXR_GRAPHIC0_SPAN 0x0028
-#define MXR_GRAPHIC0_SXY 0x002C
-#define MXR_GRAPHIC0_WH 0x0030
-#define MXR_GRAPHIC0_DXY 0x0034
-#define MXR_GRAPHIC0_BLANK 0x0038
-#define MXR_GRAPHIC1_CFG 0x0040
-#define MXR_GRAPHIC1_BASE 0x0044
-#define MXR_GRAPHIC1_SPAN 0x0048
-#define MXR_GRAPHIC1_SXY 0x004C
-#define MXR_GRAPHIC1_WH 0x0050
-#define MXR_GRAPHIC1_DXY 0x0054
-#define MXR_GRAPHIC1_BLANK 0x0058
-#define MXR_BG_CFG 0x0060
-#define MXR_BG_COLOR0 0x0064
-#define MXR_BG_COLOR1 0x0068
-#define MXR_BG_COLOR2 0x006C
-#define MXR_CM_COEFF_Y 0x0080
-#define MXR_CM_COEFF_CB 0x0084
-#define MXR_CM_COEFF_CR 0x0088
-#define MXR_GRAPHIC0_BASE_S 0x2024
-#define MXR_GRAPHIC1_BASE_S 0x2044
-
-/* for parametrized access to layer registers */
-#define MXR_GRAPHIC_CFG(i) (0x0020 + (i) * 0x20)
-#define MXR_GRAPHIC_BASE(i) (0x0024 + (i) * 0x20)
-#define MXR_GRAPHIC_SPAN(i) (0x0028 + (i) * 0x20)
-#define MXR_GRAPHIC_SXY(i) (0x002C + (i) * 0x20)
-#define MXR_GRAPHIC_WH(i) (0x0030 + (i) * 0x20)
-#define MXR_GRAPHIC_DXY(i) (0x0034 + (i) * 0x20)
-#define MXR_GRAPHIC_BLANK(i) (0x0038 + (i) * 0x20)
-#define MXR_GRAPHIC_BASE_S(i) (0x2024 + (i) * 0x20)
-
-/*
- * Bit definition part
- */
-
-/* generates mask for range of bits */
-#define MXR_MASK(high_bit, low_bit) \
- (((2 << ((high_bit) - (low_bit))) - 1) << (low_bit))
-
-#define MXR_MASK_VAL(val, high_bit, low_bit) \
- (((val) << (low_bit)) & MXR_MASK(high_bit, low_bit))
-
-/* bits for MXR_STATUS */
-#define MXR_STATUS_16_BURST (1 << 7)
-#define MXR_STATUS_BURST_MASK (1 << 7)
-#define MXR_STATUS_BIG_ENDIAN (1 << 3)
-#define MXR_STATUS_ENDIAN_MASK (1 << 3)
-#define MXR_STATUS_SYNC_ENABLE (1 << 2)
-#define MXR_STATUS_REG_RUN (1 << 0)
-
-/* bits for MXR_CFG */
-#define MXR_CFG_RGB601_0_255 (0 << 9)
-#define MXR_CFG_RGB601_16_235 (1 << 9)
-#define MXR_CFG_RGB709_0_255 (2 << 9)
-#define MXR_CFG_RGB709_16_235 (3 << 9)
-#define MXR_CFG_RGB_FMT_MASK 0x600
-#define MXR_CFG_OUT_YUV444 (0 << 8)
-#define MXR_CFG_OUT_RGB888 (1 << 8)
-#define MXR_CFG_OUT_MASK (1 << 8)
-#define MXR_CFG_DST_SDO (0 << 7)
-#define MXR_CFG_DST_HDMI (1 << 7)
-#define MXR_CFG_DST_MASK (1 << 7)
-#define MXR_CFG_SCAN_HD_720 (0 << 6)
-#define MXR_CFG_SCAN_HD_1080 (1 << 6)
-#define MXR_CFG_GRP1_ENABLE (1 << 5)
-#define MXR_CFG_GRP0_ENABLE (1 << 4)
-#define MXR_CFG_VP_ENABLE (1 << 3)
-#define MXR_CFG_SCAN_INTERLACE (0 << 2)
-#define MXR_CFG_SCAN_PROGRASSIVE (1 << 2)
-#define MXR_CFG_SCAN_NTSC (0 << 1)
-#define MXR_CFG_SCAN_PAL (1 << 1)
-#define MXR_CFG_SCAN_SD (0 << 0)
-#define MXR_CFG_SCAN_HD (1 << 0)
-#define MXR_CFG_SCAN_MASK 0x47
-
-/* bits for MXR_GRAPHICn_CFG */
-#define MXR_GRP_CFG_COLOR_KEY_DISABLE (1 << 21)
-#define MXR_GRP_CFG_BLEND_PRE_MUL (1 << 20)
-#define MXR_GRP_CFG_WIN_BLEND_EN (1 << 17)
-#define MXR_GRP_CFG_PIXEL_BLEND_EN (1 << 16)
-#define MXR_GRP_CFG_FORMAT_VAL(x) MXR_MASK_VAL(x, 11, 8)
-#define MXR_GRP_CFG_FORMAT_MASK MXR_GRP_CFG_FORMAT_VAL(~0)
-#define MXR_GRP_CFG_ALPHA_VAL(x) MXR_MASK_VAL(x, 7, 0)
-
-/* bits for MXR_GRAPHICn_WH */
-#define MXR_GRP_WH_H_SCALE(x) MXR_MASK_VAL(x, 28, 28)
-#define MXR_GRP_WH_V_SCALE(x) MXR_MASK_VAL(x, 12, 12)
-#define MXR_GRP_WH_WIDTH(x) MXR_MASK_VAL(x, 26, 16)
-#define MXR_GRP_WH_HEIGHT(x) MXR_MASK_VAL(x, 10, 0)
-
-/* bits for MXR_GRAPHICn_SXY */
-#define MXR_GRP_SXY_SX(x) MXR_MASK_VAL(x, 26, 16)
-#define MXR_GRP_SXY_SY(x) MXR_MASK_VAL(x, 10, 0)
-
-/* bits for MXR_GRAPHICn_DXY */
-#define MXR_GRP_DXY_DX(x) MXR_MASK_VAL(x, 26, 16)
-#define MXR_GRP_DXY_DY(x) MXR_MASK_VAL(x, 10, 0)
-
-/* bits for MXR_INT_EN */
-#define MXR_INT_EN_VSYNC (1 << 11)
-#define MXR_INT_EN_ALL (0x0f << 8)
-
-/* bit for MXR_INT_STATUS */
-#define MXR_INT_CLEAR_VSYNC (1 << 11)
-#define MXR_INT_STATUS_VSYNC (1 << 0)
-
-/* bit for MXR_LAYER_CFG */
-#define MXR_LAYER_CFG_GRP1_VAL(x) MXR_MASK_VAL(x, 11, 8)
-#define MXR_LAYER_CFG_GRP0_VAL(x) MXR_MASK_VAL(x, 7, 4)
-#define MXR_LAYER_CFG_VP_VAL(x) MXR_MASK_VAL(x, 3, 0)
-
-#endif /* SAMSUNG_REGS_MIXER_H */
-
diff --git a/drivers/gpu/drm/exynos_tmp/regs-vp.h b/drivers/gpu/drm/exynos_tmp/regs-vp.h
deleted file mode 100644
index 10b737a..0000000
--- a/drivers/gpu/drm/exynos_tmp/regs-vp.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *
- * Cloned from drivers/media/video/s5p-tv/regs-vp.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Video processor register header file for Samsung Mixer driver
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef SAMSUNG_REGS_VP_H
-#define SAMSUNG_REGS_VP_H
-
-/*
- * Register part
- */
-
-#define VP_ENABLE 0x0000
-#define VP_SRESET 0x0004
-#define VP_SHADOW_UPDATE 0x0008
-#define VP_FIELD_ID 0x000C
-#define VP_MODE 0x0010
-#define VP_IMG_SIZE_Y 0x0014
-#define VP_IMG_SIZE_C 0x0018
-#define VP_PER_RATE_CTRL 0x001C
-#define VP_TOP_Y_PTR 0x0028
-#define VP_BOT_Y_PTR 0x002C
-#define VP_TOP_C_PTR 0x0030
-#define VP_BOT_C_PTR 0x0034
-#define VP_ENDIAN_MODE 0x03CC
-#define VP_SRC_H_POSITION 0x0044
-#define VP_SRC_V_POSITION 0x0048
-#define VP_SRC_WIDTH 0x004C
-#define VP_SRC_HEIGHT 0x0050
-#define VP_DST_H_POSITION 0x0054
-#define VP_DST_V_POSITION 0x0058
-#define VP_DST_WIDTH 0x005C
-#define VP_DST_HEIGHT 0x0060
-#define VP_H_RATIO 0x0064
-#define VP_V_RATIO 0x0068
-#define VP_POLY8_Y0_LL 0x006C
-#define VP_POLY4_Y0_LL 0x00EC
-#define VP_POLY4_C0_LL 0x012C
-
-/*
- * Bit definition part
- */
-
-/* generates mask for range of bits */
-
-#define VP_MASK(high_bit, low_bit) \
- (((2 << ((high_bit) - (low_bit))) - 1) << (low_bit))
-
-#define VP_MASK_VAL(val, high_bit, low_bit) \
- (((val) << (low_bit)) & VP_MASK(high_bit, low_bit))
-
- /* VP_ENABLE */
-#define VP_ENABLE_ON (1 << 0)
-
-/* VP_SRESET */
-#define VP_SRESET_PROCESSING (1 << 0)
-
-/* VP_SHADOW_UPDATE */
-#define VP_SHADOW_UPDATE_ENABLE (1 << 0)
-
-/* VP_MODE */
-#define VP_MODE_NV12 (0 << 6)
-#define VP_MODE_NV21 (1 << 6)
-#define VP_MODE_LINE_SKIP (1 << 5)
-#define VP_MODE_MEM_LINEAR (0 << 4)
-#define VP_MODE_MEM_TILED (1 << 4)
-#define VP_MODE_FMT_MASK (5 << 4)
-#define VP_MODE_FIELD_ID_AUTO_TOGGLING (1 << 2)
-#define VP_MODE_2D_IPC (1 << 1)
-
-/* VP_IMG_SIZE_Y */
-/* VP_IMG_SIZE_C */
-#define VP_IMG_HSIZE(x) VP_MASK_VAL(x, 29, 16)
-#define VP_IMG_VSIZE(x) VP_MASK_VAL(x, 13, 0)
-
-/* VP_SRC_H_POSITION */
-#define VP_SRC_H_POSITION_VAL(x) VP_MASK_VAL(x, 14, 4)
-
-/* VP_ENDIAN_MODE */
-#define VP_ENDIAN_MODE_LITTLE (1 << 0)
-
-#endif /* SAMSUNG_REGS_VP_H */
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 92101e3..028d1fa 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1411,7 +1411,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
if (args->buffer_count < 1 ||
args->buffer_count > UINT_MAX / sizeof(*exec2_list)) {
- DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count);
+ DRM_DEBUG("execbuf2 with %d buffers\n", args->buffer_count);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6bbc686..f797daf 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8591,7 +8591,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
- for_each_pipe(pipe) {
+ for_each_pipe(pipe)
I915_WRITE(DSPCNTR(pipe),
I915_READ(DSPCNTR(pipe)) |
DISPPLANE_TRICKLE_FEED_DISABLE);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 491aa9e..95db2e9 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -733,6 +733,30 @@ static const struct dmi_system_id intel_no_lvds[] = {
},
{
.callback = intel_no_lvds_dmi_callback,
+ .ident = "Asus AT5NM10T-I",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
+ },
+ },
+ {
+ .callback = intel_no_lvds_dmi_callback,
+ .ident = "Hewlett-Packard t5745",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_BOARD_NAME, "hp t5745"),
+ },
+ },
+ {
+ .callback = intel_no_lvds_dmi_callback,
+ .ident = "Hewlett-Packard st5747",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_BOARD_NAME, "hp st5747"),
+ },
+ },
+ {
+ .callback = intel_no_lvds_dmi_callback,
.ident = "MSI Wind Box DC500",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 9edbf14..466db41 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -3408,17 +3408,6 @@ int evergreen_init(struct radeon_device *rdev)
}
}
- /* Don't start up if the MC ucode is missing on BTC parts.
- * The default clocks and voltages before the MC ucode
- * is loaded are not suffient for advanced operations.
- */
- if (ASIC_IS_DCE5(rdev)) {
- if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) {
- DRM_ERROR("radeon: MC ucode required for NI+.\n");
- return -EINVAL;
- }
- }
-
return 0;
}
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 0970bed..ae356cf 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2244,8 +2244,7 @@ void r100_bm_disable(struct radeon_device *rdev)
WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000040);
tmp = RREG32(RADEON_BUS_CNTL);
mdelay(1);
- pci_read_config_word(rdev->pdev, 0x4, &tmp16);
- pci_write_config_word(rdev->pdev, 0x4, tmp16 & 0xFFFB);
+ pci_clear_master(rdev->pdev);
mdelay(1);
}
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index e9f7662..d25cf86 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -341,16 +341,6 @@ void rs600_hpd_fini(struct radeon_device *rdev)
}
}
-void rs600_bm_disable(struct radeon_device *rdev)
-{
- u16 tmp;
-
- /* disable bus mastering */
- pci_read_config_word(rdev->pdev, 0x4, &tmp);
- pci_write_config_word(rdev->pdev, 0x4, tmp & 0xFFFB);
- mdelay(1);
-}
-
int rs600_asic_reset(struct radeon_device *rdev)
{
struct rv515_mc_save save;