Merge remote-tracking branch 'stable/linux-5.15.y' into rpi-5.15.y
authorDom Cobley <popcornmix@gmail.com>
Mon, 11 Apr 2022 12:01:36 +0000 (13:01 +0100)
committerDom Cobley <popcornmix@gmail.com>
Mon, 11 Apr 2022 12:01:36 +0000 (13:01 +0100)
27 files changed:
1  2 
arch/arm/boot/dts/bcm2711.dtsi
drivers/bluetooth/hci_h5.c
drivers/char/hw_random/Kconfig
drivers/clk/clk.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/i915/display/intel_hdmi.c
drivers/gpu/drm/v3d/v3d_drv.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/i2c/busses/i2c-bcm2835.c
drivers/media/v4l2-core/v4l2-ctrls-core.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/media/v4l2-core/v4l2-mem2mem.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/phy/broadcom.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
drivers/pps/clients/pps-gpio.c
drivers/spi/spi.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/video/fbdev/core/fbmem.c
kernel/resource.c
mm/page_alloc.c
sound/soc/codecs/Kconfig
sound/soc/soc-core.c

Simple merge
Simple merge
Simple merge
Simple merge
@@@ -5032,15 -5033,9 +5033,15 @@@ static void drm_parse_hdmi_deep_color_i
                  connector->name, dc_bpc);
        info->bpc = dc_bpc;
  
 +      /*
 +       * Deep color support mandates RGB444 support for all video
 +       * modes.
 +       */
 +      info->color_formats |= DRM_COLOR_FORMAT_RGB444;
 +
        /* YCRCB444 is optional according to spec. */
        if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
-               info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
+               info->edid_hdmi_ycbcr444_dc_modes = info->edid_hdmi_rgb444_dc_modes;
                DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
                          connector->name);
        }
Simple merge
@@@ -1515,287 -1029,51 +1515,287 @@@ static void vc4_hdmi_encoder_post_crtc_
                   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
                   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
  
 -      HDMI_WRITE(HDMI_VID_CTL,
 -                 HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX);
 +      HDMI_WRITE(HDMI_VID_CTL,
 +                 HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX);
 +
 +      if (vc4_encoder->hdmi_monitor) {
 +              HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 +                         HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 +                         VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 +
 +              spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 +
 +              ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 +                             VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
 +              WARN_ONCE(ret, "Timeout waiting for "
 +                        "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
 +      } else {
 +              HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
 +                         HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 +                         ~(VC4_HDMI_RAM_PACKET_ENABLE));
 +              HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 +                         HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 +                         ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 +
 +              spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 +
 +              ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 +                               VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
 +              WARN_ONCE(ret, "Timeout waiting for "
 +                        "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
 +      }
 +
 +      if (vc4_encoder->hdmi_monitor) {
 +              spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 +
 +              WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 +                        VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
 +              HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 +                         HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 +                         VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
 +
 +              HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
 +                         VC4_HDMI_RAM_PACKET_ENABLE);
 +
 +              spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 +              vc4_hdmi->output_enabled = true;
 +
 +              vc4_hdmi_set_infoframes(encoder);
 +      }
 +
 +      vc4_hdmi_recenter_fifo(vc4_hdmi);
 +      vc4_hdmi_enable_scrambling(encoder);
 +
 +      mutex_unlock(&vc4_hdmi->mutex);
 +}
 +
 +static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,
 +                                           struct drm_crtc_state *crtc_state,
 +                                           struct drm_connector_state *conn_state)
 +{
 +      struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 +      struct vc4_hdmi_connector_state *vc4_state =
 +              conn_state_to_vc4_hdmi_conn_state(conn_state);
 +
 +      mutex_lock(&vc4_hdmi->mutex);
 +      vc4_hdmi->output_bpc = vc4_state->output_bpc;
 +      vc4_hdmi->output_format = vc4_state->output_format;
 +      vc4_hdmi->broadcast_rgb = vc4_state->broadcast_rgb;
 +      memcpy(&vc4_hdmi->saved_adjusted_mode,
 +             &crtc_state->adjusted_mode,
 +             sizeof(vc4_hdmi->saved_adjusted_mode));
 +      mutex_unlock(&vc4_hdmi->mutex);
 +}
 +
 +static bool
 +vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi *vc4_hdmi,
 +                                const struct drm_display_info *info,
 +                                const struct drm_display_mode *mode,
 +                                unsigned int format, unsigned int bpc)
 +{
 +      struct drm_device *dev = vc4_hdmi->connector.dev;
 +      u8 vic = drm_match_cea_mode(mode);
 +
 +      if (vic == 1 && bpc != 8) {
 +              drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc);
 +              return false;
 +      }
 +
 +      if (!info->is_hdmi &&
 +          (format != VC4_HDMI_OUTPUT_RGB || bpc != 8)) {
 +              drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n");
 +              return false;
 +      }
 +
 +      switch (format) {
 +      case VC4_HDMI_OUTPUT_RGB:
 +              drm_dbg(dev, "RGB Format, checking the constraints.\n");
 +
-               if (bpc == 10 && !(info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)) {
++              if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) {
 +                      drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
 +                      return false;
 +              }
 +
-               if (bpc == 12 && !(info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36)) {
++              if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) {
 +                      drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
 +                      return false;
 +              }
 +
 +              drm_dbg(dev, "RGB format supported in that configuration.\n");
 +
 +              return true;
 +
 +      case VC4_HDMI_OUTPUT_YUV422:
 +              drm_dbg(dev, "YUV422 format, checking the constraints.\n");
 +
 +              if (!(info->color_formats & DRM_COLOR_FORMAT_YCRCB422)) {
 +                      drm_dbg(dev, "Sink doesn't support YUV422.\n");
 +                      return false;
 +              }
 +
 +              if (bpc != 12) {
 +                      drm_dbg(dev, "YUV422 only supports 12 bpc.\n");
 +                      return false;
 +              }
 +
 +              drm_dbg(dev, "YUV422 format supported in that configuration.\n");
 +
 +              return true;
 +
 +      case VC4_HDMI_OUTPUT_YUV444:
 +              drm_dbg(dev, "YUV444 format, checking the constraints.\n");
 +
 +              if (!(info->color_formats & DRM_COLOR_FORMAT_YCRCB444)) {
 +                      drm_dbg(dev, "Sink doesn't support YUV444.\n");
 +                      return false;
 +              }
 +
-               if (bpc == 10 && !(info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)) {
++              if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) {
 +                      drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
 +                      return false;
 +              }
 +
-               if (bpc == 12 && !(info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36)) {
++              if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) {
 +                      drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
 +                      return false;
 +              }
 +
 +              drm_dbg(dev, "YUV444 format supported in that configuration.\n");
 +
 +              return true;
 +      }
 +
 +      return false;
 +}
 +
 +static enum drm_mode_status
 +vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi,
 +                           unsigned long long clock)
 +{
 +      const struct drm_connector *connector = &vc4_hdmi->connector;
 +      const struct drm_display_info *info = &connector->display_info;
 +
 +      if (clock > vc4_hdmi->variant->max_pixel_clock)
 +              return MODE_CLOCK_HIGH;
 +
 +      if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK)
 +              return MODE_CLOCK_HIGH;
 +
 +      if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
 +              return MODE_CLOCK_HIGH;
 +
 +      return MODE_OK;
 +}
 +
 +static unsigned long long
 +vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode,
 +                                  unsigned int bpc,
 +                                  enum vc4_hdmi_output_format fmt)
 +{
 +      unsigned long long clock = mode->clock * 1000;
 +
 +      if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 +              clock = clock * 2;
 +
 +      if (fmt == VC4_HDMI_OUTPUT_YUV422)
 +              bpc = 8;
 +
 +      return clock * bpc / 8;
 +}
 +
 +static int
 +vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi,
 +                             struct vc4_hdmi_connector_state *vc4_state,
 +                             const struct drm_display_mode *mode,
 +                             unsigned int bpc, unsigned int fmt)
 +{
 +      unsigned long long clock;
 +
 +      clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt);
 +      if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, clock) != MODE_OK)
 +              return -EINVAL;
 +
 +      vc4_state->pixel_rate = clock;
 +
 +      return 0;
 +}
 +
 +static int
 +vc4_hdmi_encoder_compute_format(const struct vc4_hdmi *vc4_hdmi,
 +                              struct vc4_hdmi_connector_state *vc4_state,
 +                              const struct drm_display_mode *mode,
 +                              unsigned int bpc)
 +{
 +      struct drm_device *dev = vc4_hdmi->connector.dev;
 +      const struct drm_connector *connector = &vc4_hdmi->connector;
 +      const struct drm_display_info *info = &connector->display_info;
 +      unsigned int format;
  
 -      if (vc4_encoder->hdmi_monitor) {
 -              HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 -                         HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 -                         VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 +      drm_dbg(dev, "Trying with an RGB output\n");
  
 -              ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 -                             VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
 -              WARN_ONCE(ret, "Timeout waiting for "
 -                        "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
 -      } else {
 -              HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
 -                         HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 -                         ~(VC4_HDMI_RAM_PACKET_ENABLE));
 -              HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 -                         HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 -                         ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 +      format = VC4_HDMI_OUTPUT_RGB;
 +      if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) {
 +              int ret;
  
 -              ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 -                               VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
 -              WARN_ONCE(ret, "Timeout waiting for "
 -                        "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
 +              ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state,
 +                                                   mode, bpc, format);
 +              if (!ret) {
 +                      vc4_state->output_format = format;
 +                      return 0;
 +              }
        }
  
 -      if (vc4_encoder->hdmi_monitor) {
 -              WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 -                        VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
 -              HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 -                         HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 -                         VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
 +      drm_dbg(dev, "Failed, Trying with an YUV422 output\n");
  
 -              HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
 -                         VC4_HDMI_RAM_PACKET_ENABLE);
 +      format = VC4_HDMI_OUTPUT_YUV422;
 +      if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) {
 +              int ret;
  
 -              vc4_hdmi_set_infoframes(encoder);
 +              ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state,
 +                                                   mode, bpc, format);
 +              if (!ret) {
 +                      vc4_state->output_format = format;
 +                      return 0;
 +              }
        }
  
 -      vc4_hdmi_recenter_fifo(vc4_hdmi);
 -      vc4_hdmi_enable_scrambling(encoder);
 +      drm_dbg(dev, "Failed. No Format Supported for that bpc count.\n");
 +
 +      return -EINVAL;
  }
  
 -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 +static int
 +vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi,
 +                              struct vc4_hdmi_connector_state *vc4_state,
 +                              const struct drm_display_mode *mode)
  {
 +      struct drm_device *dev = vc4_hdmi->connector.dev;
 +      struct drm_connector_state *conn_state = &vc4_state->base;
 +      unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12);
 +      unsigned int bpc;
 +      int ret;
 +
 +      for (bpc = max_bpc; bpc >= 8; bpc -= 2) {
 +              drm_dbg(dev, "Trying with a %d bpc output\n", bpc);
 +
 +              ret = vc4_hdmi_encoder_compute_format(vc4_hdmi, vc4_state,
 +                                                    mode, bpc);
 +              if (ret)
 +                      continue;
 +
 +              vc4_state->output_bpc = bpc;
 +
 +              drm_dbg(dev,
 +                      "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n",
 +                      mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
 +                      vc4_state->output_bpc,
 +                      vc4_hdmi_output_fmt_str(vc4_state->output_format),
 +                      vc4_state->pixel_rate);
 +
 +              break;
 +      }
 +
 +      return ret;
  }
  
  #define WIFI_2_4GHz_CH1_MIN_FREQ      2400000000ULL
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc mm/page_alloc.c
Simple merge
Simple merge
Simple merge