Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
1
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
0984772
Documentation
LICENSES
arch
block
certs
crypto
drivers
accessibility
acpi
amba
android
ata
atm
auxdisplay
base
bcma
block
bluetooth
bus
cdrom
char
clk
clocksource
comedi
connector
counter
cpufreq
cpuidle
crypto
cxl
dax
dca
devfreq
dio
dma-buf
dma
edac
eisa
extcon
firewire
firmware
fpga
fsi
gnss
gpio
gpu
drm
amd
arm
armada
aspeed
ast
atmel-hlcdc
bridge
display
etnaviv
exynos
fsl-dcu
gma500
gud
hisilicon
hyperv
i2c
i810
i915
imx
ingenic
kmb
lib
lima
logicvc
mcde
mediatek
meson
Kconfig
Makefile
meson_crtc.c
meson_crtc.h
meson_drv.c
meson_drv.h
meson_dw_hdmi.c
meson_dw_hdmi.h
meson_encoder_cvbs.c
meson_encoder_cvbs.h
meson_encoder_hdmi.c
meson_encoder_hdmi.h
meson_osd_afbcd.c
meson_osd_afbcd.h
meson_overlay.c
meson_overlay.h
meson_plane.c
meson_plane.h
meson_rdma.c
meson_rdma.h
meson_registers.h
meson_vclk.c
meson_vclk.h
meson_venc.c
meson_venc.h
meson_viu.c
meson_viu.h
meson_vpp.c
meson_vpp.h
mga
mgag200
msm
mxsfb
nouveau
omapdrm
panel
panfrost
pl111
qxl
r128
radeon
rcar-du
rockchip
savage
scheduler
shmobile
sis
solomon
sprd
sti
stm
sun4i
tdfx
tegra
tests
tidss
tilcdc
tiny
ttm
tve200
udl
v3d
vboxvideo
vc4
vgem
via
virtio
vkms
vmwgfx
xen
xlnx
Kconfig
Makefile
drm_agpsupport.c
drm_aperture.c
drm_atomic.c
drm_atomic_helper.c
drm_atomic_state_helper.c
drm_atomic_uapi.c
drm_auth.c
drm_blend.c
drm_bridge.c
drm_bridge_connector.c
drm_buddy.c
drm_bufs.c
drm_cache.c
drm_client.c
drm_client_modeset.c
drm_color_mgmt.c
drm_connector.c
drm_context.c
drm_crtc.c
drm_crtc_helper.c
drm_crtc_helper_internal.h
drm_crtc_internal.h
drm_damage_helper.c
drm_debugfs.c
drm_debugfs_crc.c
drm_displayid.c
drm_dma.c
drm_drv.c
drm_dumb_buffers.c
drm_edid.c
drm_edid_load.c
drm_encoder.c
drm_encoder_slave.c
drm_fb_dma_helper.c
drm_fb_helper.c
drm_file.c
drm_flip_work.c
drm_format_helper.c
drm_fourcc.c
drm_framebuffer.c
drm_gem.c
drm_gem_atomic_helper.c
drm_gem_dma_helper.c
drm_gem_framebuffer_helper.c
drm_gem_shmem_helper.c
drm_gem_ttm_helper.c
drm_gem_vram_helper.c
drm_hashtab.c
drm_internal.h
drm_ioc32.c
drm_ioctl.c
drm_irq.c
drm_kms_helper_common.c
drm_lease.c
drm_legacy.h
drm_legacy_misc.c
drm_lock.c
drm_managed.c
drm_memory.c
drm_mipi_dbi.c
drm_mipi_dsi.c
drm_mm.c
drm_mode_config.c
drm_mode_object.c
drm_modes.c
drm_modeset_helper.c
drm_modeset_lock.c
drm_nomodeset.c
drm_of.c
drm_panel.c
drm_panel_orientation_quirks.c
drm_pci.c
drm_plane.c
drm_plane_helper.c
drm_prime.c
drm_print.c
drm_privacy_screen.c
drm_privacy_screen_x86.c
drm_probe_helper.c
drm_property.c
drm_rect.c
drm_scatter.c
drm_self_refresh_helper.c
drm_simple_kms_helper.c
drm_syncobj.c
drm_sysfs.c
drm_trace.h
drm_trace_points.c
drm_vblank.c
drm_vblank_work.c
drm_vm.c
drm_vma_manager.c
drm_writeback.c
host1x
ipu-v3
trace
vga
Makefile
greybus
hid
hsi
hte
hv
hwmon
hwspinlock
hwtracing
i2c
i3c
idle
iio
infiniband
input
interconnect
iommu
ipack
irqchip
isdn
leds
macintosh
mailbox
mcb
md
media
memory
memstick
message
mfd
misc
mmc
most
mtd
mux
net
nfc
ntb
nubus
nvdimm
nvme
nvmem
of
opp
parisc
parport
pci
pcmcia
peci
perf
phy
pinctrl
platform
pnp
power
powercap
pps
ps3
ptp
pwm
rapidio
ras
regulator
remoteproc
reset
rpmsg
rtc
s390
sbus
scsi
sh
siox
slimbus
soc
soundwire
spi
spmi
ssb
staging
target
tc
tee
thermal
thunderbolt
tty
ufs
uio
usb
vdpa
vfio
vhost
video
virt
virtio
vlynq
w1
watchdog
xen
zorro
Kconfig
Makefile
fs
include
init
io_uring
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
usr
virt
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
drivers
/
gpu
/
drm
/
meson
/
meson_encoder_hdmi.c
Copy path
Blame
Blame
Latest commit
History
History
475 lines (378 loc) · 14.1 KB
Breadcrumbs
linux
/
drivers
/
gpu
/
drm
/
meson
/
meson_encoder_hdmi.c
Top
File metadata and controls
Code
Blame
475 lines (378 loc) · 14.1 KB
Raw
// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2016 BayLibre, SAS * Author: Neil Armstrong <narmstrong@baylibre.com> * Copyright (C) 2015 Amlogic, Inc. All rights reserved. */ #include <linux/clk.h> #include <linux/component.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of_device.h> #include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/reset.h> #include <media/cec-notifier.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_bridge_connector.h> #include <drm/drm_device.h> #include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <linux/media-bus-format.h> #include <linux/videodev2.h> #include "meson_drv.h" #include "meson_registers.h" #include "meson_vclk.h" #include "meson_venc.h" #include "meson_encoder_hdmi.h" struct meson_encoder_hdmi { struct drm_encoder encoder; struct drm_bridge bridge; struct drm_bridge *next_bridge; struct drm_connector *connector; struct meson_drm *priv; unsigned long output_bus_fmt; struct cec_notifier *cec_notifier; }; #define bridge_to_meson_encoder_hdmi(x) \ container_of(x, struct meson_encoder_hdmi, bridge) static int meson_encoder_hdmi_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); return drm_bridge_attach(bridge->encoder, encoder_hdmi->next_bridge, &encoder_hdmi->bridge, flags); } static void meson_encoder_hdmi_detach(struct drm_bridge *bridge) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); cec_notifier_conn_unregister(encoder_hdmi->cec_notifier); encoder_hdmi->cec_notifier = NULL; } static void meson_encoder_hdmi_set_vclk(struct meson_encoder_hdmi *encoder_hdmi, const struct drm_display_mode *mode) { struct meson_drm *priv = encoder_hdmi->priv; int vic = drm_match_cea_mode(mode); unsigned int phy_freq; unsigned int vclk_freq; unsigned int venc_freq; unsigned int hdmi_freq; vclk_freq = mode->clock; /* For 420, pixel clock is half unlike venc clock */ if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) vclk_freq /= 2; /* TMDS clock is pixel_clock * 10 */ phy_freq = vclk_freq * 10; if (!vic) { meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq, vclk_freq, vclk_freq, vclk_freq, false); return; } /* 480i/576i needs global pixel doubling */ if (mode->flags & DRM_MODE_FLAG_DBLCLK) vclk_freq *= 2; venc_freq = vclk_freq; hdmi_freq = vclk_freq; /* VENC double pixels for 1080i, 720p and YUV420 modes */ if (meson_venc_hdmi_venc_repeat(vic) || encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) venc_freq *= 2; vclk_freq = max(venc_freq, hdmi_freq); if (mode->flags & DRM_MODE_FLAG_DBLCLK) venc_freq /= 2; dev_dbg(priv->dev, "vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n", phy_freq, vclk_freq, venc_freq, hdmi_freq, priv->venc.hdmi_use_enci); meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq, venc_freq, hdmi_freq, priv->venc.hdmi_use_enci); } static enum drm_mode_status meson_encoder_hdmi_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *display_info, const struct drm_display_mode *mode) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); struct meson_drm *priv = encoder_hdmi->priv; bool is_hdmi2_sink = display_info->hdmi.scdc.supported; unsigned int phy_freq; unsigned int vclk_freq; unsigned int venc_freq; unsigned int hdmi_freq; int vic = drm_match_cea_mode(mode); enum drm_mode_status status; dev_dbg(priv->dev, "Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */ if (display_info->max_tmds_clock && mode->clock > display_info->max_tmds_clock && !drm_mode_is_420_only(display_info, mode) && !drm_mode_is_420_also(display_info, mode)) return MODE_BAD; /* Check against non-VIC supported modes */ if (!vic) { status = meson_venc_hdmi_supported_mode(mode); if (status != MODE_OK) return status; return meson_vclk_dmt_supported_freq(priv, mode->clock); /* Check against supported VIC modes */ } else if (!meson_venc_hdmi_supported_vic(vic)) return MODE_BAD; vclk_freq = mode->clock; /* For 420, pixel clock is half unlike venc clock */ if (drm_mode_is_420_only(display_info, mode) || (!is_hdmi2_sink && drm_mode_is_420_also(display_info, mode))) vclk_freq /= 2; /* TMDS clock is pixel_clock * 10 */ phy_freq = vclk_freq * 10; /* 480i/576i needs global pixel doubling */ if (mode->flags & DRM_MODE_FLAG_DBLCLK) vclk_freq *= 2; venc_freq = vclk_freq; hdmi_freq = vclk_freq; /* VENC double pixels for 1080i, 720p and YUV420 modes */ if (meson_venc_hdmi_venc_repeat(vic) || drm_mode_is_420_only(display_info, mode) || (!is_hdmi2_sink && drm_mode_is_420_also(display_info, mode))) venc_freq *= 2; vclk_freq = max(venc_freq, hdmi_freq); if (mode->flags & DRM_MODE_FLAG_DBLCLK) venc_freq /= 2; dev_dbg(priv->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n", __func__, phy_freq, vclk_freq, venc_freq, hdmi_freq); return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq); } static void meson_encoder_hdmi_atomic_enable(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); struct drm_atomic_state *state = bridge_state->base.state; unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR; struct meson_drm *priv = encoder_hdmi->priv; struct drm_connector_state *conn_state; const struct drm_display_mode *mode; struct drm_crtc_state *crtc_state; struct drm_connector *connector; bool yuv420_mode = false; int vic; connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); if (WARN_ON(!connector)) return; conn_state = drm_atomic_get_new_connector_state(state, connector); if (WARN_ON(!conn_state)) return; crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); if (WARN_ON(!crtc_state)) return; mode = &crtc_state->adjusted_mode; vic = drm_match_cea_mode(mode); dev_dbg(priv->dev, "\"%s\" vic %d\n", mode->name, vic); if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) { ycrcb_map = VPU_HDMI_OUTPUT_CRYCB; yuv420_mode = true; } else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16) ycrcb_map = VPU_HDMI_OUTPUT_CRYCB; /* VENC + VENC-DVI Mode setup */ meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode); /* VCLK Set clock */ meson_encoder_hdmi_set_vclk(encoder_hdmi, mode); if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) /* Setup YUV420 to HDMI-TX, no 10bit diphering */ writel_relaxed(2 | (2 << 2), priv->io_base + _REG(VPU_HDMI_FMT_CTRL)); else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16) /* Setup YUV422 to HDMI-TX, no 10bit diphering */ writel_relaxed(1 | (2 << 2), priv->io_base + _REG(VPU_HDMI_FMT_CTRL)); else /* Setup YUV444 to HDMI-TX, no 10bit diphering */ writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL)); dev_dbg(priv->dev, "%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP"); if (priv->venc.hdmi_use_enci) writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN)); else writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN)); } static void meson_encoder_hdmi_atomic_disable(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); struct meson_drm *priv = encoder_hdmi->priv; writel_bits_relaxed(0x3, 0, priv->io_base + _REG(VPU_HDMI_SETTING)); writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN)); } static const u32 meson_encoder_hdmi_out_bus_fmts[] = { MEDIA_BUS_FMT_YUV8_1X24, MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_UYYVYY8_0_5X24, }; static u32 * meson_encoder_hdmi_get_inp_bus_fmts(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state, u32 output_fmt, unsigned int *num_input_fmts) { u32 *input_fmts = NULL; int i; *num_input_fmts = 0; for (i = 0 ; i < ARRAY_SIZE(meson_encoder_hdmi_out_bus_fmts) ; ++i) { if (output_fmt == meson_encoder_hdmi_out_bus_fmts[i]) { *num_input_fmts = 1; input_fmts = kcalloc(*num_input_fmts, sizeof(*input_fmts), GFP_KERNEL); if (!input_fmts) return NULL; input_fmts[0] = output_fmt; break; } } return input_fmts; } static int meson_encoder_hdmi_atomic_check(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); struct drm_connector_state *old_conn_state = drm_atomic_get_old_connector_state(conn_state->state, conn_state->connector); struct meson_drm *priv = encoder_hdmi->priv; encoder_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format; dev_dbg(priv->dev, "output_bus_fmt %lx\n", encoder_hdmi->output_bus_fmt); if (!drm_connector_atomic_hdr_metadata_equal(old_conn_state, conn_state)) crtc_state->mode_changed = true; return 0; } static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge, enum drm_connector_status status) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); struct edid *edid; if (!encoder_hdmi->cec_notifier) return; if (status == connector_status_connected) { edid = drm_bridge_get_edid(encoder_hdmi->next_bridge, encoder_hdmi->connector); if (!edid) return; cec_notifier_set_phys_addr_from_edid(encoder_hdmi->cec_notifier, edid); } else cec_notifier_phys_addr_invalidate(encoder_hdmi->cec_notifier); } static const struct drm_bridge_funcs meson_encoder_hdmi_bridge_funcs = { .attach = meson_encoder_hdmi_attach, .detach = meson_encoder_hdmi_detach, .mode_valid = meson_encoder_hdmi_mode_valid, .hpd_notify = meson_encoder_hdmi_hpd_notify, .atomic_enable = meson_encoder_hdmi_atomic_enable, .atomic_disable = meson_encoder_hdmi_atomic_disable, .atomic_get_input_bus_fmts = meson_encoder_hdmi_get_inp_bus_fmts, .atomic_check = meson_encoder_hdmi_atomic_check, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_reset = drm_atomic_helper_bridge_reset, }; int meson_encoder_hdmi_init(struct meson_drm *priv) { struct meson_encoder_hdmi *meson_encoder_hdmi; struct platform_device *pdev; struct device_node *remote; int ret; meson_encoder_hdmi = devm_kzalloc(priv->dev, sizeof(*meson_encoder_hdmi), GFP_KERNEL); if (!meson_encoder_hdmi) return -ENOMEM; /* HDMI Transceiver Bridge */ remote = of_graph_get_remote_node(priv->dev->of_node, 1, 0); if (!remote) { dev_err(priv->dev, "HDMI transceiver device is disabled"); return 0; } meson_encoder_hdmi->next_bridge = of_drm_find_bridge(remote); if (!meson_encoder_hdmi->next_bridge) { dev_err(priv->dev, "Failed to find HDMI transceiver bridge\n"); ret = -EPROBE_DEFER; goto err_put_node; } /* HDMI Encoder Bridge */ meson_encoder_hdmi->bridge.funcs = &meson_encoder_hdmi_bridge_funcs; meson_encoder_hdmi->bridge.of_node = priv->dev->of_node; meson_encoder_hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; meson_encoder_hdmi->bridge.interlace_allowed = true; drm_bridge_add(&meson_encoder_hdmi->bridge); meson_encoder_hdmi->priv = priv; /* Encoder */ ret = drm_simple_encoder_init(priv->drm, &meson_encoder_hdmi->encoder, DRM_MODE_ENCODER_TMDS); if (ret) { dev_err(priv->dev, "Failed to init HDMI encoder: %d\n", ret); goto err_put_node; } meson_encoder_hdmi->encoder.possible_crtcs = BIT(0); /* Attach HDMI Encoder Bridge to Encoder */ ret = drm_bridge_attach(&meson_encoder_hdmi->encoder, &meson_encoder_hdmi->bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (ret) { dev_err(priv->dev, "Failed to attach bridge: %d\n", ret); goto err_put_node; } /* Initialize & attach Bridge Connector */ meson_encoder_hdmi->connector = drm_bridge_connector_init(priv->drm, &meson_encoder_hdmi->encoder); if (IS_ERR(meson_encoder_hdmi->connector)) { dev_err(priv->dev, "Unable to create HDMI bridge connector\n"); ret = PTR_ERR(meson_encoder_hdmi->connector); goto err_put_node; } drm_connector_attach_encoder(meson_encoder_hdmi->connector, &meson_encoder_hdmi->encoder); /* * We should have now in place: * encoder->[hdmi encoder bridge]->[dw-hdmi bridge]->[display connector bridge]->[display connector] */ /* * drm_connector_attach_max_bpc_property() requires the * connector to have a state. */ drm_atomic_helper_connector_reset(meson_encoder_hdmi->connector); if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) || meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) || meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) drm_connector_attach_hdr_output_metadata_property(meson_encoder_hdmi->connector); drm_connector_attach_max_bpc_property(meson_encoder_hdmi->connector, 8, 8); /* Handle this here until handled by drm_bridge_connector_init() */ meson_encoder_hdmi->connector->ycbcr_420_allowed = true; pdev = of_find_device_by_node(remote); of_node_put(remote); if (pdev) { struct cec_connector_info conn_info; struct cec_notifier *notifier; cec_fill_conn_info_from_drm(&conn_info, meson_encoder_hdmi->connector); notifier = cec_notifier_conn_register(&pdev->dev, NULL, &conn_info); if (!notifier) { put_device(&pdev->dev); return -ENOMEM; } meson_encoder_hdmi->cec_notifier = notifier; } priv->encoders[MESON_ENC_HDMI] = meson_encoder_hdmi; dev_dbg(priv->dev, "HDMI encoder initialized\n"); return 0; err_put_node: of_node_put(remote); return ret; } void meson_encoder_hdmi_remove(struct meson_drm *priv) { struct meson_encoder_hdmi *meson_encoder_hdmi; if (priv->encoders[MESON_ENC_HDMI]) { meson_encoder_hdmi = priv->encoders[MESON_ENC_HDMI]; drm_bridge_remove(&meson_encoder_hdmi->bridge); drm_bridge_remove(meson_encoder_hdmi->next_bridge); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
You can’t perform that action at this time.