···110110 ret = connector_status_connected;111111 else112112 ret = connector_status_disconnected;113113+ } else if (dssdev->type == OMAP_DISPLAY_TYPE_DPI ||114114+ dssdev->type == OMAP_DISPLAY_TYPE_DBI ||115115+ dssdev->type == OMAP_DISPLAY_TYPE_SDI ||116116+ dssdev->type == OMAP_DISPLAY_TYPE_DSI) {117117+ ret = connector_status_connected;113118 } else {114119 ret = connector_status_unknown;115120 }···194189 struct omap_video_timings timings = {0};195190 struct drm_device *dev = connector->dev;196191 struct drm_display_mode *new_mode;197197- int ret = MODE_BAD;192192+ int r, ret = MODE_BAD;198193199194 copy_timings_drm_to_omap(&timings, mode);200195 mode->vrefresh = drm_mode_vrefresh(mode);201196202202- if (!dssdrv->check_timings(dssdev, &timings)) {197197+ /*198198+ * if the panel driver doesn't have a check_timings, it's most likely199199+ * a fixed resolution panel, check if the timings match with the200200+ * panel's timings201201+ */202202+ if (dssdrv->check_timings) {203203+ r = dssdrv->check_timings(dssdev, &timings);204204+ } else {205205+ struct omap_video_timings t = {0};206206+207207+ dssdrv->get_timings(dssdev, &t);208208+209209+ if (memcmp(&timings, &t, sizeof(struct omap_video_timings)))210210+ r = -EINVAL;211211+ else212212+ r = 0;213213+ }214214+215215+ if (!r) {203216 /* check if vrefresh is still valid */204217 new_mode = drm_mode_duplicate(dev, mode);205218 new_mode->clock = timings.pixel_clock;
+14-7
drivers/gpu/drm/omapdrm/omap_crtc.c
···7474 struct work_struct page_flip_work;7575};76767777+uint32_t pipe2vbl(struct drm_crtc *crtc)7878+{7979+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);8080+8181+ return dispc_mgr_get_vsync_irq(omap_crtc->channel);8282+}8383+7784/*7885 * Manager-ops, callbacks from output when they need to configure7986 * the upstream part of the video pipe.···620613 omap_crtc->apply.pre_apply = omap_crtc_pre_apply;621614 omap_crtc->apply.post_apply = omap_crtc_post_apply;622615623623- omap_crtc->apply_irq.irqmask = pipe2vbl(id);616616+ omap_crtc->channel = channel;617617+ omap_crtc->plane = plane;618618+ omap_crtc->plane->crtc = crtc;619619+ omap_crtc->name = channel_names[channel];620620+ omap_crtc->pipe = id;621621+622622+ omap_crtc->apply_irq.irqmask = pipe2vbl(crtc);624623 omap_crtc->apply_irq.irq = omap_crtc_apply_irq;625624626625 omap_crtc->error_irq.irqmask =627626 dispc_mgr_get_sync_lost_irq(channel);628627 omap_crtc->error_irq.irq = omap_crtc_error_irq;629628 omap_irq_register(dev, &omap_crtc->error_irq);630630-631631- omap_crtc->channel = channel;632632- omap_crtc->plane = plane;633633- omap_crtc->plane->crtc = crtc;634634- omap_crtc->name = channel_names[channel];635635- omap_crtc->pipe = id;636629637630 /* temporary: */638631 omap_crtc->mgr.id = channel;
+133-32
drivers/gpu/drm/omapdrm/omap_drv.c
···7474 }7575}76767777+static bool channel_used(struct drm_device *dev, enum omap_channel channel)7878+{7979+ struct omap_drm_private *priv = dev->dev_private;8080+ int i;8181+8282+ for (i = 0; i < priv->num_crtcs; i++) {8383+ struct drm_crtc *crtc = priv->crtcs[i];8484+8585+ if (omap_crtc_channel(crtc) == channel)8686+ return true;8787+ }8888+8989+ return false;9090+}9191+7792static int omap_modeset_init(struct drm_device *dev)7893{7994 struct omap_drm_private *priv = dev->dev_private;8095 struct omap_dss_device *dssdev = NULL;8196 int num_ovls = dss_feat_get_num_ovls();8282- int id;9797+ int num_mgrs = dss_feat_get_num_mgrs();9898+ int num_crtcs;9999+ int i, id = 0;8310084101 drm_mode_config_init(dev);8510286103 omap_drm_irq_install(dev);8710488105 /*8989- * Create private planes and CRTCs for the last NUM_CRTCs overlay9090- * plus manager:106106+ * We usually don't want to create a CRTC for each manager, at least107107+ * not until we have a way to expose private planes to userspace.108108+ * Otherwise there would not be enough video pipes left for drm planes.109109+ * We use the num_crtc argument to limit the number of crtcs we create.91110 */9292- for (id = 0; id < min(num_crtc, num_ovls); id++) {9393- struct drm_plane *plane;9494- struct drm_crtc *crtc;111111+ num_crtcs = min3(num_crtc, num_mgrs, num_ovls);951129696- plane = omap_plane_init(dev, id, true);9797- crtc = omap_crtc_init(dev, plane, pipe2chan(id), id);9898-9999- BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));100100- priv->crtcs[id] = crtc;101101- priv->num_crtcs++;102102-103103- priv->planes[id] = plane;104104- priv->num_planes++;105105- }106106-107107- /*108108- * Create normal planes for the remaining overlays:109109- */110110- for (; id < num_ovls; id++) {111111- struct drm_plane *plane = omap_plane_init(dev, id, false);112112-113113- BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));114114- priv->planes[priv->num_planes++] = plane;115115- }113113+ dssdev = NULL;116114117115 for_each_dss_dev(dssdev) {118116 struct drm_connector *connector;119117 struct drm_encoder *encoder;118118+ enum omap_channel channel;120119121120 if (!dssdev->driver) {122121 dev_warn(dev->dev, "%s has no driver.. skipping it\n",123122 dssdev->name);124124- return 0;123123+ continue;125124 }126125127126 if (!(dssdev->driver->get_timings ||···128129 dev_warn(dev->dev, "%s driver does not support "129130 "get_timings or read_edid.. skipping it!\n",130131 dssdev->name);131131- return 0;132132+ continue;132133 }133134134135 encoder = omap_encoder_init(dev, dssdev);···156157157158 drm_mode_connector_attach_encoder(connector, encoder);158159160160+ /*161161+ * if we have reached the limit of the crtcs we are allowed to162162+ * create, let's not try to look for a crtc for this163163+ * panel/encoder and onwards, we will, of course, populate the164164+ * the possible_crtcs field for all the encoders with the final165165+ * set of crtcs we create166166+ */167167+ if (id == num_crtcs)168168+ continue;169169+170170+ /*171171+ * get the recommended DISPC channel for this encoder. For now,172172+ * we only try to get create a crtc out of the recommended, the173173+ * other possible channels to which the encoder can connect are174174+ * not considered.175175+ */176176+ channel = dssdev->output->dispc_channel;177177+178178+ /*179179+ * if this channel hasn't already been taken by a previously180180+ * allocated crtc, we create a new crtc for it181181+ */182182+ if (!channel_used(dev, channel)) {183183+ struct drm_plane *plane;184184+ struct drm_crtc *crtc;185185+186186+ plane = omap_plane_init(dev, id, true);187187+ crtc = omap_crtc_init(dev, plane, channel, id);188188+189189+ BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));190190+ priv->crtcs[id] = crtc;191191+ priv->num_crtcs++;192192+193193+ priv->planes[id] = plane;194194+ priv->num_planes++;195195+196196+ id++;197197+ }198198+ }199199+200200+ /*201201+ * we have allocated crtcs according to the need of the panels/encoders,202202+ * adding more crtcs here if needed203203+ */204204+ for (; id < num_crtcs; id++) {205205+206206+ /* find a free manager for this crtc */207207+ for (i = 0; i < num_mgrs; i++) {208208+ if (!channel_used(dev, i)) {209209+ struct drm_plane *plane;210210+ struct drm_crtc *crtc;211211+212212+ plane = omap_plane_init(dev, id, true);213213+ crtc = omap_crtc_init(dev, plane, i, id);214214+215215+ BUG_ON(priv->num_crtcs >=216216+ ARRAY_SIZE(priv->crtcs));217217+218218+ priv->crtcs[id] = crtc;219219+ priv->num_crtcs++;220220+221221+ priv->planes[id] = plane;222222+ priv->num_planes++;223223+224224+ break;225225+ } else {226226+ continue;227227+ }228228+ }229229+230230+ if (i == num_mgrs) {231231+ /* this shouldn't really happen */232232+ dev_err(dev->dev, "no managers left for crtc\n");233233+ return -ENOMEM;234234+ }235235+ }236236+237237+ /*238238+ * Create normal planes for the remaining overlays:239239+ */240240+ for (; id < num_ovls; id++) {241241+ struct drm_plane *plane = omap_plane_init(dev, id, false);242242+243243+ BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));244244+ priv->planes[priv->num_planes++] = plane;245245+ }246246+247247+ for (i = 0; i < priv->num_encoders; i++) {248248+ struct drm_encoder *encoder = priv->encoders[i];249249+ struct omap_dss_device *dssdev =250250+ omap_encoder_get_dssdev(encoder);251251+159252 /* figure out which crtc's we can connect the encoder to: */160253 encoder->possible_crtcs = 0;161254 for (id = 0; id < priv->num_crtcs; id++) {162162- enum omap_dss_output_id supported_outputs =163163- dss_feat_get_supported_outputs(pipe2chan(id));255255+ struct drm_crtc *crtc = priv->crtcs[id];256256+ enum omap_channel crtc_channel;257257+ enum omap_dss_output_id supported_outputs;258258+259259+ crtc_channel = omap_crtc_channel(crtc);260260+ supported_outputs =261261+ dss_feat_get_supported_outputs(crtc_channel);262262+164263 if (supported_outputs & dssdev->output->id)165264 encoder->possible_crtcs |= (1 << id);166265 }167266 }267267+268268+ DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n",269269+ priv->num_planes, priv->num_crtcs, priv->num_encoders,270270+ priv->num_connectors);168271169272 dev->mode_config.min_width = 32;170273 dev->mode_config.min_height = 32;···404303 return ret;405304}406305407407-struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {306306+static struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {408307 DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH),409308 DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),410309 DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH),···668567};669568#endif670569671671-struct platform_driver pdev = {570570+static struct platform_driver pdev = {672571 .driver = {673572 .name = DRIVER_NAME,674573 .owner = THIS_MODULE,
+4-34
drivers/gpu/drm/omapdrm/omap_drv.h
···139139int omap_gem_resume(struct device *dev);140140#endif141141142142-int omap_irq_enable_vblank(struct drm_device *dev, int crtc);143143-void omap_irq_disable_vblank(struct drm_device *dev, int crtc);142142+int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id);143143+void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id);144144irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);145145void omap_irq_preinstall(struct drm_device *dev);146146int omap_irq_postinstall(struct drm_device *dev);···271271 return ALIGN(pitch, 8 * bytespp);272272}273273274274-static inline enum omap_channel pipe2chan(int pipe)275275-{276276- int num_mgrs = dss_feat_get_num_mgrs();277277-278278- /*279279- * We usually don't want to create a CRTC for each manager,280280- * at least not until we have a way to expose private planes281281- * to userspace. Otherwise there would not be enough video282282- * pipes left for drm planes. The higher #'d managers tend283283- * to have more features so start in reverse order.284284- */285285- return num_mgrs - pipe - 1;286286-}287287-288274/* map crtc to vblank mask */289289-static inline uint32_t pipe2vbl(int crtc)290290-{291291- enum omap_channel channel = pipe2chan(crtc);292292- return dispc_mgr_get_vsync_irq(channel);293293-}294294-295295-static inline int crtc2pipe(struct drm_device *dev, struct drm_crtc *crtc)296296-{297297- struct omap_drm_private *priv = dev->dev_private;298298- int i;299299-300300- for (i = 0; i < ARRAY_SIZE(priv->crtcs); i++)301301- if (priv->crtcs[i] == crtc)302302- return i;303303-304304- BUG(); /* bogus CRTC ptr */305305- return -1;306306-}275275+uint32_t pipe2vbl(struct drm_crtc *crtc);276276+struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder);307277308278/* should these be made into common util helpers?309279 */
+22-2
drivers/gpu/drm/omapdrm/omap_encoder.c
···4141 struct omap_dss_device *dssdev;4242};43434444+struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder)4545+{4646+ struct omap_encoder *omap_encoder = to_omap_encoder(encoder);4747+4848+ return omap_encoder->dssdev;4949+}5050+4451static void omap_encoder_destroy(struct drm_encoder *encoder)4552{4653 struct omap_encoder *omap_encoder = to_omap_encoder(encoder);···135128136129 dssdev->output->manager = mgr;137130138138- ret = dssdrv->check_timings(dssdev, timings);131131+ if (dssdrv->check_timings) {132132+ ret = dssdrv->check_timings(dssdev, timings);133133+ } else {134134+ struct omap_video_timings t = {0};135135+136136+ dssdrv->get_timings(dssdev, &t);137137+138138+ if (memcmp(timings, &t, sizeof(struct omap_video_timings)))139139+ ret = -EINVAL;140140+ else141141+ ret = 0;142142+ }143143+139144 if (ret) {140145 dev_err(dev->dev, "could not set timings: %d\n", ret);141146 return ret;142147 }143148144144- dssdrv->set_timings(dssdev, timings);149149+ if (dssdrv->set_timings)150150+ dssdrv->set_timings(dssdev, timings);145151146152 return 0;147153}
···130130 * Zero on success, appropriate errno if the given @crtc's vblank131131 * interrupt cannot be enabled.132132 */133133-int omap_irq_enable_vblank(struct drm_device *dev, int crtc)133133+int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id)134134{135135 struct omap_drm_private *priv = dev->dev_private;136136+ struct drm_crtc *crtc = priv->crtcs[crtc_id];136137 unsigned long flags;137138138138- DBG("dev=%p, crtc=%d", dev, crtc);139139+ DBG("dev=%p, crtc=%d", dev, crtc_id);139140140141 dispc_runtime_get();141142 spin_lock_irqsave(&list_lock, flags);···157156 * a hardware vblank counter, this routine should be a no-op, since158157 * interrupts will have to stay on to keep the count accurate.159158 */160160-void omap_irq_disable_vblank(struct drm_device *dev, int crtc)159159+void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id)161160{162161 struct omap_drm_private *priv = dev->dev_private;162162+ struct drm_crtc *crtc = priv->crtcs[crtc_id];163163 unsigned long flags;164164165165- DBG("dev=%p, crtc=%d", dev, crtc);165165+ DBG("dev=%p, crtc=%d", dev, crtc_id);166166167167 dispc_runtime_get();168168 spin_lock_irqsave(&list_lock, flags);···188186189187 VERB("irqs: %08x", irqstatus);190188191191- for (id = 0; id < priv->num_crtcs; id++)192192- if (irqstatus & pipe2vbl(id))189189+ for (id = 0; id < priv->num_crtcs; id++) {190190+ struct drm_crtc *crtc = priv->crtcs[id];191191+192192+ if (irqstatus & pipe2vbl(crtc))193193 drm_handle_vblank(dev, id);194194+ }194195195196 spin_lock_irqsave(&list_lock, flags);196197 list_for_each_entry_safe(handler, n, &priv->irq_list, node) {