void CSTmV29IFrames::UpdateFrame(void)
{
  stm_meta_data_t *m;

  if(!m_pCurrentMode)
    return;

  DEBUGF2(4,("%s\n",__PRETTY_FUNCTION__));

  if(m_pGamutQueue && ((m = m_pGamutQueue->Pop()) != 0))
  {
    stm_hdmi_info_frame_t *i = (stm_hdmi_info_frame_t*)&m->data[0];
    WriteInfoFrameHelper(0,i);
    /*
     * Note: the hardware slots are numbered from 1 not zero.
     */
    m_ulConfig &= ~STM_HDMI_IFRAME_CFG_DI_n(STM_HDMI_IFRAME_MASK,1);
    m_ulConfig |= STM_HDMI_IFRAME_CFG_DI_n(STM_HDMI_IFRAME_FIELD,1);
    stm_meta_data_release(m);
  }

  /*
   * Color gamut and ISRC packets should be mutually exclusive, if they are
   * both present then the following call will overwrite the gamut data we
   * have just set.
   */
  CSTmIFrameManager::UpdateFrame();

}
void CSTmV29IFrames::ProcessInfoFrameComplete(ULONG interruptStatus)
{
  stm_meta_data_t *m;

  /*
   * If we got a completion interrupt after being stopped, ignore it
   */
  if(!m_pCurrentMode)
    return;

  /*
   * If the first slot isn't setup to update each field we haven't started any
   * gamut packets, so nothing more to do.
   */
  if((m_ulConfig & STM_HDMI_IFRAME_MASK) != STM_HDMI_IFRAME_FIELD)
    return;

  if(m_pGamutQueue && ((m = m_pGamutQueue->Pop()) != 0))
  {
    stm_hdmi_info_frame_t *i = (stm_hdmi_info_frame_t*)&m->data[0];
    WriteInfoFrameHelper(0,i);
    stm_meta_data_release(m);
  }

}
Ejemplo n.º 3
0
static int stmfb_set_picture_configuration(struct stmfbio_picture_configuration *cfg, struct stmfb_info *i)
{
  stm_meta_data_result_t res;
  stm_meta_data_t *metadata;
  stm_picture_format_info_t *pic_info;
  unsigned long flags;
  int ret = 0;

  if((cfg->flags & STMFBIO_PICTURE_FLAGS_PICUTRE_ASPECT) &&
     (cfg->picture_aspect > STMFBIO_PIC_PICTURE_ASPECT_16_9))
    return -EINVAL;

  if((cfg->flags & STMFBIO_PICTURE_FLAGS_VIDEO_ASPECT) &&
     (cfg->video_aspect > STMFBIO_PIC_VIDEO_ASPECT_GT_16_9))
    return -EINVAL;

  if((cfg->flags & STMFBIO_PICTURE_FLAGS_LETTERBOX) &&
     (cfg->letterbox_style > STMFBIO_PIC_LETTERBOX_SAP_4_3))
    return -EINVAL;

  if((cfg->flags & STMFBIO_PICTURE_FLAGS_RESCALE_INFO) &&
     (cfg->picture_rescale > STMFBIO_PIC_RESCALE_BOTH))
    return -EINVAL;

  if((metadata = kzalloc(sizeof(stm_meta_data_t)+sizeof(stm_picture_format_info_t),GFP_KERNEL)) == 0)
    return -ENOMEM;

  metadata->size      = sizeof(stm_meta_data_t)+sizeof(stm_picture_format_info_t);
  metadata->type      = STM_METADATA_TYPE_PICTURE_INFO;
  /*
   * We need to hold a reference for the metadata as we need to queue
   * the same thing twice (to analogue and HDMI outputs) and need to ensure we
   * do not get any race conditions in the lifetime of the object. We use the
   * metadata addref/release internal helpers to manage this. We must use
   * the release under interrupt lock once a queue has been successful to
   * ensure it is atomic with the VTG interrupt processing, but we actually do
   * this all the time to make the point and stop the code from
   * breaking in future changes.
   */
  spin_lock_irqsave(&i->framebufferSpinLock,flags);
  stm_meta_data_addref(metadata);
  spin_unlock_irqrestore(&i->framebufferSpinLock,flags);

  metadata->release   = (void(*)(struct stm_meta_data_s*))kfree;
  metadata->presentationTime = ((TIME64)cfg->timestamp.tv_sec * USEC_PER_SEC) +
                                (TIME64)cfg->timestamp.tv_usec;

  pic_info = (stm_picture_format_info_t*)&metadata->data[0];
  pic_info->flags           = cfg->flags;
  pic_info->pictureAspect   = (stm_wss_t)cfg->picture_aspect;
  pic_info->videoAspect     = (stm_wss_t)cfg->video_aspect;
  pic_info->letterboxStyle  = (stm_letterbox_t)cfg->letterbox_style;
  pic_info->pictureRescale  = (stm_picture_rescale_t)cfg->picture_rescale;
  pic_info->barEnable       = cfg->bar_enable;
  pic_info->topEndLine      = cfg->top_bar_end;
  pic_info->bottomStartLine = cfg->bottom_bar_start;
  pic_info->leftEndPixel    = cfg->left_bar_end;
  pic_info->rightStartPixel = cfg->right_bar_start;

  if(stm_display_output_queue_metadata(i->pFBMainOutput, metadata, &res)<0)
  {
    ret = signal_pending(current)?-EINTR:-EIO;
    goto exit;
  }

  /*
   * Set first stab at the wanted return value, this is likely to be revised
   * below.
   */
  ret = stmfb_convert_metadata_result_to_errno(res);

  if(i->hdmi == NULL)
  {
    /*
     * Display pipeline has no HDMI transmitter so just return this result.
     */
    goto exit;
  }

  switch(res)
  {
    case STM_METADATA_RES_OK:
    case STM_METADATA_RES_QUEUE_UNAVAILABLE:
      /*
       * If the DENC isn't in use the queue will not be available,
       * but that is fine we can continue to HDMI.
       */
      break;
    default:
      goto exit;
  }

  if(mutex_lock_interruptible(&i->hdmi->lock))
  {
    ret = -EINTR;
    goto exit;
  }

  /*
   * DVI or undetermined sink does not have InfoFrames.
   */
  if(i->hdmi->edid_info.display_type != STM_DISPLAY_HDMI)
    goto mutex_exit;


  if((i->hdmi->status != STM_DISPLAY_CONNECTED) &&
     (metadata->presentationTime == 0LL))
  {
    /*
     * This is a slight of hand for the usual case that a change
     * is required immediately but the HDMI output is currently
     * stopped and will not process its metadata queues. Flush the queue
     * because we know this request will be the valid data as soon
     * as the HDMI output is started again.
     */
    stm_display_output_flush_metadata(i->hdmi->hdmi_output,STM_METADATA_TYPE_PICTURE_INFO);
  }


  if(stm_display_output_queue_metadata(i->hdmi->hdmi_output, metadata, &res)<0)
  {
    ret = signal_pending(current)?-EINTR:-EIO;
    goto mutex_exit;
  }

  ret = stmfb_convert_metadata_result_to_errno(res);

mutex_exit:
  mutex_unlock(&i->hdmi->lock);
exit:
  spin_lock_irqsave(&i->framebufferSpinLock,flags);
  stm_meta_data_release(metadata);
  spin_unlock_irqrestore(&i->framebufferSpinLock,flags);

  return ret;
}